My 11″ 2020 iPad Pro is one of the best devices I’ve ever used; it might even just be my most favorite Device. It’s sleek, it’s portable, it’s modular, it’s beautiful, and it’s fast. However, it’s held back by the limiting nature of iPadOS; since most of the limitations I’ve run into are merely software problems, and the A12Z chip in my iPad is more than capable of handling what I want it to do (this is the same processor that was used in Apple’s Developer Transition Kit, so it was plenty powerful to run Mac apps), I’ve been on a search to contort this touch-first device into something able to accommodate my diverse set of needs.
One of these needs is coding, and specifically, coding for WordPress web development. The iPad is not nearly as flexible when it comes to this type of work, mostly because of its filesystem. Being a modern device, the iPad has done its best to abstract the filesystem away (which is fine, since normal people don’t think like that anyway), making it harder for me to manage projects thanks to app sandboxing and other genuinely good features. Just, not good for me. But hey, since it’s all software, there’s always solutions to be found.
There are many tutorials online on how to code from an iPad. Some suggest setting up a
code-server instance, some suggest using Google Cloud to run a virtual machine, and other people I found have created a workflow using native iPad apps. All of these were too complicated for my taste, or didn’t accommodate for my particular workflow. So, before I introduce to you my own complicated workflow, let me first discuss my needs.
My needs are (theoretically) simple:
- I want to be able to access my projects, dependencies, and workspaces from any device I touch.
- I want to access these projects from any location.
- I want to use Visual Studio Code.
- I want to focus on web development technologies like PHP and React.
- I want to code from my iPad!
- Oh, and I would like to do this for free or using stuff I already have.
These are all reasonable needs, albeit complex to set up, and a vanilla setup using Visual Studio Code and
code tunnels would probably be enough. However, since I develop primarily for WordPress (both PHP and React), this means I need to build out some additional infrastructure.
The biggest issue would be building a solution that allowed me to access my code and development sites across the web. Since WordPress hard-codes the URL into its database, it’s not like I can access a site assigned to
localhost on a server somewhere using a random IP address, since it would just redirect back to
localhost. And, unfortunately, WordPress Playground isn’t mature enough to develop on.
So, I know what my needs are. How should I go about building this system?
Here are the tools I chose to go with:
- My old Windows laptop
- Visual Studio Code
If you have old hardware lying around (preferably x86-based, but that’s for another article), the rest of what you need should presumably be free! You might not even need to use a VM or Hyper-V, but I wanted to just for fun.
I have an old Windows laptop I store in my closet. It’s always running, but outside of acting as a fileshare, it doesn’t do much. This is the device I chose to run my development server on. However, I prefer working in a *NIX environment, and I still need my OS to run Windows for some other services, so I decided to take advantage of the hardware’s Hyper-V support and run Ubuntu virtually.
This isn’t something I recommend doing, and it adds so much more complexity to the setup. However, I like it, since I can run all my utilities and have a familiar terminal experience as I do on my Mac. I also get the benefits that Hyper-V has, such as snapshots and backup. Also also, theoretically there’s a sandbox layer that should protect me if my VM gets compromised.
Visual Studio Code Server
In my research I remember seeing something about a Visual Studio Code server, but I remember it being limited: it was an open-source project by a 3rd party and it did not have access to VSCode’s Extensions library. These were limitations I was willing to accept.
Weirdly enough, it took me a while to re-find
code-server. That’s because something else kept appearing in my Google results, seemingly throwing me off the trail. This something else was Visual Studio Code Server, which is a set of extensions that are built into VSCode and integrate with
vscode.dev, the online version of VSCode hosted by Microsoft. This is basically a way to host your own VSCode instance, but without tons of configuration (you install VSCode and run
code tunnel from a terminal). Since it was developed by Microsoft, it also supports Microsoft’s marketplace of extensions.
VSCode also integrates with GitHub, and even offers remote tunneling and port forwarding built in. The tunneling allows me to access the server from anywhere, the port forwarding means that I can forward my
localhost ports from my local computer to my remote computer (or is it vice-versa?). You can learn more about VSCode’s Remote Tunnels here:
VSCode got me 90% of the way there. However, I found out in my testing that port-forwarding doesn’t really work for WordPress sites, at least when using VSCode from an iPad.
On a laptop, I can SSH into my server and actually forward ports from the host to the client, and the client takes the ports on as its own. Not so on an iPad; due to there being no
hosts file on an iPad, Microsoft instead sets up a proxy URL that tunnels into the host computer. This is a great solution, and it would work in any other instance; however, due to WordPress’ hard-coded database URL, the tunnel sends me to a local IP address that doesn’t work. I can’t change the WordPress site URL to the tunnel’s URL either, since the tunnel URL is assigned at random and changes every time the tunnel is closed and re-opened.
So, all that to say, using Tailscale (within the VM) is the way to go here. Every device added to the Tailscale tenant gets assigned an IP address that doesn’t seem to change. Plus, you can access those devices from anywhere, as long as you’re using Tailscale on both the client and the host. It eats more battery, but it works quickly and reliably, and it’s technically safer!
WordPress + LocalWP
The platform I’m using to host WordPress sites is LocalWP. This is a fantastic app that makes it a breeze to set up multiple local development WordPress instances, something I still have a hard time doing manually. This solution is great since it seems to work in Hyper-V, and comes with another important feature:
As opposed to DevKinsta, my preferred local development tool, LocalWP does not use virtualization or Docker. This means that, 1) I can use this within a virtual container like Hyper-V, and 2) it’s not using some weird virtualized network or
This means that the websites are acting on the physical network, which means I can manually change the WordPress site address to my local Tailscale IP! LocalWP complains about there being a Site URL mismatch, but simply ignoring the warning is harmless and I’m left with an easy-to-manage set of WordPress instances segmented by port number.
Problems and Troubleshooting
This setup works great. It’s stable, reliable, and accessible. I can access my code environment remotely, my terminal remotely (through VSCode or Tailscale and SSH), and I can access my WordPress sites remotely. However, the one problem I’ve noticed while testing this setup is that iPad multitasking is unreliable.
The iPad is not good at keeping the VSCode instance in state. There are many times I’ve found myself switching between apps and coming back to a blank VSCode window that now has to load from scratch.
This has a pretty nasty ramification: since I develop with React, I run terminal watchers, like
npm start, that forever run until stopped. A lot of those processes build my code. When I switch back to a blank VSCode window on my iPad, or if my Mac loses network connection, VSCode has to reload and any processes that were running are still running. Worse still, the terminal session is lost, which means that my process is running in the background somewhere, unable to be terminated without a complete server restart (or some hardcore terminal process drilling that I’m not familiar enough with).
The solution? I started using
tmux, a terminal window manager. This allowed me to create instances of my terminal that I could switch to, even if my session was disconnected. Just a quick
tmux attach-session -t name-of-session and boom, I’d be back to where I was! This is such a cool tool, and it has other benefits, such as being able to run VSCode’s
code tunnel in the background without leaving a Terminal window open on my dev server.
So, this infrastructure allows me to work remotely from almost anything, which is great. But how specifically can I work from my iPad?
Unfortunately, my iPad is the generation right before the M1 version, which means I don’t get goodies like multi-window Stage Manager. However, I do get Stage Manager, albeit for just one screen (which can then be mirrored). So, I can get my multi-window fix that way. It’s hard on an 11″ screen, but it’s manageable.
And it works! I can run Tailscale on my iPad and VPN into my server. VSCode can be accessed via
vscode.dev, and I can add that to my homescreen to turn it into its own app. Finally, I use a combination of Terminus and ShellFish to SSH into my server if I want to quickly send commands or move files around. If I need to do something with the GUI, I can use Google’s awesome Chrome Remote Desktop web app to make sure my LocalWP instance is up and running.
That’s my setup in a nutshell: A server running Ubuntu (through Hyper-V), with installs of Tailscale, LocalWP, VSCode, and tmux. This set of software allows me to code on my iPad with ease, and Stage Manager makes it so I can have Tailscale, Safari, VSCode, and an SSH client running on my tablet’s screen at the same time. I can access everything on my server remotely, and it’s fast.
There are some reliability concerns, and the screen can become cramped. However, this solution allows me to switch between devices with ease, which is especially great for testing (since I can also get my local websites on my phone!).
I’ll keep everyone updated on how this process goes and what issues I run into. Hopefully you’ve found this article helpful! Let me know how you’ve approached this problem, or other similar problems, in the comments section.