So I lost my primary laptop dell xps to a motherboard failure and then other backup dell vostro to some parrot os booting issue(was trying to set up solana ecosystem and messed up with parrot os and I had set up bios admin password and didn’t remember which meant I cannot reinstall parrot os using live usb or any other os as it requires changing boot order). Currently I have almost zero money so no money to buy new laptop . I booked a laptop on rent and started searching for ways to get this bios admin password reset. (SPOILER ALERT: I was not able to get bios admin password reset and ultimately had to sell both laptops cheap. There were various reasons but main reason ZERO MONEY. The rented laptop did arrive though after 2 weeks but by that time I did not needed it)
While searching for options and also waiting for a rented laptop to arrive I started searching for ways to do development on iPhone. I found ish app. It is emulator based on alpine Linux and you can download Linux packages. But its very low powered one and simulates 32 bit architecture and can’t support latest versions of many packages.I was developing on Rust and wanted to work on a project on Solana blockchain with Anchor framework. Failed to get even rust development started on ish as I was able to download only an old rust version (1.52.1) and my current code written in rust did not compile. Setting up solana and anchor definitely went out of window.
After spending some time brushing my Linux concept and also making a solana wallet balance checker using shell scripting ( very nicely supported and doable in ish app balance checker ) I decided to try the idea of using ish app just for coding and CI pipelines available for free on platforms like GitHub, Gitlab and Codeberg for compiling and building (SPOILER ALERT: I was able to build thr project and also deploy on devnet using just iPhone and CI pipelines. So in rest of the articles I will go about how I did it .(I do not think any one will be as desperate situation as mine but it may be some interesting read. I have also shared all the links of the solana project and the CI pipelines)).
While researching for some app to do coding I did come around some other apps like
- a-shell(good but does not have rust)
- Blink(Probably has rust pre installed. But it’s paid so did not check much )
- UTM VM : It seems like many people are able to work with it . Only complain I see is it’s slow. It allows many Linux distros and even mac and windows vm. I have old iPhone models and didn’t work for me)
I quickly settled on ish app and CI pipelines combo. While working on a project on shell scripting I started liking ish app and using CI pipelines made my work flow mirror how it is done in production work environment. Developers work on their local machines and check in their code. When code is stable it is moved to QA Testing, staging and production using CI pipelines. Also no local environment headache. I was not able to set up solana and anchor on parrot os due to some incompatible packages and then I tried to set up docker to get out of this local machine package crap but this package crap probably had already messed up with my parrot os and was not able to get into my workspace on next boot. The CI pipeline gave me same functionality of docker environment.
My setup of iPhone connected to my ducky keyboard.
Can be made more ergonomic like this
For git platform I selected Codeberg.
GitHub does not allow me to use GitHub Actions as I had some payment issue. My credit card did not work and my account was restricted. I was not able to fix this . As I mentioned earlier ZERO MONEY. I tried Gitlab next. But I was using a free VPN and sometimes it used to route me through Hong Kong servers and it turns out Gitlab does not allow to use their services there and they use to route to me a different site which was not Gitlab(But probably like Gitlab. Did not research on it). Both GitHub and Gitlab are good git platforms. GitHub very popular and Gitlab solid . But did not work for me. I then bumped into Codeberg. It’s free ( really free . No credit card crap) and also open source. (SPOILER ALERT: It worked out really nice.)
So I finalized my work set up ish app in iPhone and external ducky keyboard for coding and after I push my code to Codeberg CI will help with compiling, building and then deploying.
Following are the steps:
Install ish app from App Store
Install git vim and openssh
In ish terminal type following command
apk add git vim openssh
Configure ssh in ish
Make a .ssh directory in root folder
mkdir ~/.ssh
Get inside the .ssh folder
cd ~/.ssh
And type this command
ssh-keygen
And press enter
It will ask for your key file name and you can specify any name (i.e MyKey) if you just press enter it will take a default one. And after that you need to enter a pass phrase or keep it blank.
If you run “ls” command you will see it has created two files
MyKey is private key and needed to be kept secret. MyKey.pub it public key .
We need to copy the contents of public key
If you open Files app in iPhone you will see ish entry along side other folders .
click it and you will see various folders inside it . You will also see a root folder .

This is the folder in which we will be working in this post.
We need to copy contents of MyKey.pub and create a ssh key entry in Codeberg .
Files app does not show folders starting with “.”. So it will not be visible to us to get its contents. A workaround I followed is to copy MyKey.pub to root folder.
cp ~/.ssh/MyKey.pub ~/
Now you will see MyKey.pub in root folder .
Click on it and copy it contents. Make sure it does not have any spaces at start or end.
Create an account if you don’t have in codeberg and login.
Go to Settings page by clicking on three lines icon at top right > your profile icon > settings option.
Click on SSH/GPG keys option in Settings menu
Add a ssh key(If you are using iPhone after clicking on SSH/GPG keys option you need to scroll down to bottom to see the SSH/GPG key section)
Give any name to the newly added ssh key and paste the contents of public key you copied earlier in contents section.
Start the ssh agent and add the key with below command (please replace MyKey name with name you specified for your key)
eval “$(ssh-agent -s)”
ssh-add ~/.ssh/MyKey
Always run the above two commands whenever later you get message like this
Set up project directory
Create a blank repository in Codeberg with name profiles
Go to codeberg home page and click on three lines icon at right
And then click on create and create a repository with name profiles
Now we need to copy the ssh git url of the blank repository created earlier. Click on your profile icon , Click on Repositories menu and then click on your your newly created repository . You will see HTTPS and SSH option for git url and we need to copy ssh url. Copy the ssh url.
Open the ish app and clone the repository
git clone your_repository_copied_ssh_git_url
Now you can get inside the folder and work on your project and commit and push your code.
Create CI yaml
The focus of this post will be to show how you can use CI pipelines for compiling and deploying so I am not going to go over details of anchor framework and its components.For this tutorial sake if you are following along I would like you to copy my profiles project as zip file from codeberg, unzip and copy the contents inside profiles directory in your project root directory. The folder structure will look like this
Open .forgejo/workflows/ci.yaml . The file may look intimidating to someone who is new to CI pipelines and yaml but after you have made your first yaml file you will realise its most uncomplicated thing in the project.
Following section makes CI execute on every push . You can change the name main to the git branch you want this functionality.
name: Rust + Anchor CI
on:
push:
branches: [ main ]
pull_request:
After this you will see there are two jobs:
- build-and-test
- deploy-devnet
As obvious first one will build and execute test cases if you have provided and the second one will deploy.
Only trick thing in whole yaml is this variable DEVNET_DEPLOY_KEY_BASE64.
But before coming to this variable part to understand the workings of CI yaml I want you to go over this pdf CI yaml overview
I created this pdf with the help of Grok
I opened grok site and in the ask me anything window I typed
please explain me below Codeberg CI yaml file
and then I pressed enter and copied the contents of yaml file and clicked on send. I recommend using AI assistants to get your doubts cleared or understanding new things in general.
Assuming you have read the pdf I will come to the variable part. This is base64 string of public key.
I was not able to set up solana and anchor toolchain in ish app so I was not able to generate any public key required for devnet deploy in my ish app. To get this I used help of CI.
Check this part of code in Load devnet keypair & sync
step of build-and-test job
- name: Load devnet keypair & sync
run: |
mkdir -p ~/.config/solana
if [ -n "$DEVNET_DEPLOY_KEY_BASE64" ]; then
printf '%s' "$DEVNET_DEPLOY_KEY_BASE64" | tr -d ' \n\r\t' | base64 -d > ~/.config/solana/id.json
echo "using ecisting devnet keypair from secret"
else
echo "Error: DEVNET_DEPLOY_KEY_BASE64 secret is not set !"
exit 1
fi
solana config set --keypair ~/.config/solana/id.json
solana config set --url https://api.devnet.solana.com
solana airdrop 2 || true
anchor keys sync
It was earlier like this :
- name: Generate or load devnet keypair & sync
run: |
mkdir -p ~/.config/solana
if [ -n "$DEVNET_DEPLOY_KEY_BASE64" ]; then
echo "$DEVNET_DEPLOY_KEY_BASE64" | base64 -d > ~/.config/solana/id.json
echo "using ecisting devnet keypair from secret"
else
if [ ! -f ~/.config/solana/id.json ]; then
solana-keygen new --no-passphrase -o ~/.config/solana/id.json
echo "generated new devnet keypair"
fi
fi
solana config set --keypair ~/.config/solana/id.json
solana config set --url https://api.devnet.solana.com
solana airdrop 2 || true
anchor keys sync
Notice the separated else part if the CI does not finds the variable to be set instead of throwing error it creates a new one. After successful execution of this step you get a id.json file . After we get id.json this else part should be changed to current version. We will use the id.json file to get base 64 String and set the variable . Either you can change the else part or take this old version of CI from here old ci yaml
Now you need to enable actions in codeberg. Go to your repository settings > Units > Overview and check “Enable integrated CI/CD pipelines with Forgejo Actions” under Actions

Run following commands to commit and push all code. This will trigger the CI workflow too.
git add .
git commit -m “initial commit “
git push -u main
If you are using git first time after install you may have to set your email and name
git config --global user.email "your.email@example.com"
git config --global user.name "Your Full Name"
Go to your repository page in codeberg and you should see “…” at right side
When you click on it you will see actions option
Select actions and you will go the page where all your CI pipelines will be visible. If you are doing first then there will be only one entry
Click on the action and you should see all the step and the step on which we are generating the key should show as completed . It takes couple of minutes to complete all steps in CI yaml so wait till all steps are complete.
The file we need gets generated at this location: ~/.config/solana/id.json
Now we need base 64 string of this file to set it as value of DEVNET_DEPLOY_KEY_BASE64 variable
In ish terminal run this command
cat ~/.config/solana/id.json | base64 | tr -d '\n\r\
Copy the output and click on your profile icon in codeberg and then go to Settings option and then Actions and then Secrets. Click on add secret and enter the name DEVNET_DEPLOY_KEY_BASE64 and paste the copied base 64 in value section.
Now change your yaml file to current version in repository.
Your CI pipeline for ish and iPhone combo is all done !
Now we code on ish terminal and push our code. Pipeline run shows us if there is compilation error and test cases shows us if the functionality is working fine. If some issues we correct it, push the code and check pipeline run.
Troubleshooting
It is observed that if you are using wired external keyboard to connect to iPhone it does not connect sometimes. The solution for this is to disconnect and wait for 30 - 120 sec and the connect and it works.
Resources
Rust book
Anchor docs
Solana boot camp
AI assistants : Grok ChatGpt DeepSeek



















Top comments (0)