Yesterday I learned: how to move away from CodeAnywhere
CodeAnywhere https://codeanywhere.com/ is a cloud IDE platform that allows you to spin up containers that serve a web-based code editor and any web server you choose to run on it. Ever since moving to CodeAnywhere from Cloud9, I have been using it in my workflow of building static websites using Jekyll, because I don't want to install Ruby on Rails and Jekyll locally in my own local environment. Actual native smartphone apps was pretty much my deciding factor to picking CodeAnywhere, although that went away when they migrated from their own home-grown IDE to a web-based Eclipse Theia. I happily paid money for a monthly subscription to get me ten containers, two of which I can leave Always-On.
However, one day CodeAnywhere decided that I don't actually pay them any money, despite my credit card statement claiming the contrary, and proceeded to delete all of my "inactive" containers (except for the two Always-On). An email to their Customer Support address went unanswered except for their automated initial ack. And yet, I still continued paying them money for ten entire months for the two Always-On containers. (I procrastinate like that.)
Yesterday I needed to develop and stage a change to a Jekyll website I manage, and the container would not let me in. When I restarted the container from the CodeAnywhere dashboard, it just kept spinning and spinning and would not actually start. I was planning on taking a nap to make up for lost sleep with my ~24:00 shifts, but this was the last straw: let's move off of CodeAnywhere to... something.
My Jekyll workflow involves a git repo on GitHub, served by GitHub Pages. I make changes, get buy-in from stakeholders with a publicly-accessible jekyll serve, and then git push to GitHub to make the changes live. I briefly considered using Apple Container to set up an environment on my local computer, but that wouldn't get me a publicly-accessible staging environment without the like of Cloudflare Tunnel or Tailscale Funnel.
But then I realized that I'm an operations engineer at a cloud infrastructure company, so why not set up an environment on a cloud instance?
Apparently Oracle Cloud Infrastructure's Always Free offering is the most generous of all the large cloud services, so let's use that. I'm more familiar with Ubuntu than with Red Hat-derived distros, so no Oracle Linux for me.
After installing Ubuntu 24.04 (the latest version available on OCI) and updating, I installed code-server:
ubuntu@jekyll:~/jekyllprojects$ curl -fsSL https://code-server.dev/install.sh | sh Ubuntu 24.04.4 LTS Installing v4.123.0 of the arm64 deb package from GitHub. + mkdir -p ~/.cache/code-server + curl -#fL -o ~/.cache/code-server/code-server_4.123.0_arm64.deb.incomplete -C - https://github.com/coder/code-server/releases/download/v4.123.0/code-server_4.123.0_arm64.deb ######################################################################## 100.0% + mv ~/.cache/code-server/code-server_4.123.0_arm64.deb.incomplete ~/.cache/code-server/code-server_4.123.0_arm64.deb + sudo dpkg -i ~/.cache/code-server/code-server_4.123.0_arm64.deb Selecting previously unselected package code-server. (Reading database ... 154950 files and directories currently installed.) Preparing to unpack .../code-server_4.123.0_arm64.deb ... Unpacking code-server (4.123.0) ... Setting up code-server (4.123.0) ... deb package has been installed. To have systemd start code-server now and restart on boot: sudo systemctl enable --now code-server@$USER Or, if you don't want/need a background service you can run: code-server Deploy code-server for your team with Coder: https://github.com/coder/coder ubuntu@jekyll:~/jekyllprojects$
And edit the config file to allow connectivity from anywhere (I tightened this later):
ubuntu@jekyll:~/jekyllprojects$ cat ~/.config/code-server/config.yaml bind-addr: 127.0.0.1:8080 auth: password password: [REDACTED] cert: false ubuntu@jekyll:~/jekyllprojects$ ubuntu@jekyll:~/jekyllprojects$ ubuntu@jekyll:~/jekyllprojects$ ubuntu@jekyll:~/jekyllprojects$ cp ~/.config/code-server/config.yaml ~/.config/code-server/config.yaml.bak.initial ubuntu@jekyll:~/jekyllprojects$ vi ~/.config/code-server/config.yaml ubuntu@jekyll:~/jekyllprojects$ diff -U10 ~/.config/code-server/config.yaml.bak.initial ~/.config/code-server/config.yaml --- /home/ubuntu/.config/code-server/config.yaml.bak.initial 2026-06-04 05:18:27.452720380 +0000 +++ /home/ubuntu/.config/code-server/config.yaml 2026-06-04 05:24:06.661373119 +0000 @@ -1,4 +1,4 @@ -bind-addr: 127.0.0.1:8080 +bind-addr: 0.0.0.0:8080 auth: password password: [REDACTED] cert: false ubuntu@jekyll:~/jekyllprojects$
And add to startup
ubuntu@jekyll:~/jekyllprojects$ systemctl --user enable code-server Created symlink /home/ubuntu/.config/systemd/user/default.target.wants/code-server.service → /usr/lib/systemd/user/code-server.service. ubuntu@jekyll:~/jekyllprojects$ systemctl --user start code-server ubuntu@jekyll:~/jekyllprojects$ ubuntu@jekyll:~/jekyllprojects$ ubuntu@jekyll:~/jekyllprojects$ ubuntu@jekyll:~/jekyllprojects$ systemctl --user status code-server ● code-server.service - code-server Loaded: loaded (/usr/lib/systemd/user/code-server.service; enabled; preset: enabled) Active: active (running) since Thu 2026-06-04 05:25:58 UTC; 46s ago Main PID: 3405 (MainThread) Tasks: 22 (limit: 6964) Memory: 51.3M (peak: 51.6M) CPU: 486ms CGroup: /user.slice/user-1001.slice/[email protected]/app.slice/code-server.service ├─3405 /usr/lib/code-server/lib/node /usr/lib/code-server └─3424 /usr/lib/code-server/lib/node /usr/lib/code-server/out/node/entry Jun 04 05:25:58 jekyll systemd[1442]: Starting code-server.service - code-server... Jun 04 05:25:58 jekyll systemd[1442]: Started code-server.service - code-server. Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.305Z] info code-server 4.123.0 77d880d0c3fcbf4ac613644b3e113cedd6173a16 Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.306Z] info Using user-data-dir /home/ubuntu/.local/share/code-server Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.321Z] info Using config file /home/ubuntu/.config/code-server/config.yaml Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.321Z] info HTTP server listening on http://0.0.0.0:8080/ Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.322Z] info - Authentication is enabled Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.322Z] info - Using password from /home/ubuntu/.config/code-server/config.yaml Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.322Z] info - Not serving HTTPS Jun 04 05:25:59 jekyll code-server[3405]: [2026-06-04T05:25:59.322Z] info Session server listening on /home/ubuntu/.local/share/code-server/code-server-ipc.sock ubuntu@jekyll:~/jekyllprojects$
Next, we need to allow traffic to specific ports on the instance's virtual network on the OCI Cloud Console. Poke a hole in ingress TCP dst port 8080 from all sources 0.0.0.0/0:
And also port 4000, which we'll need later.
(It's also a good idea to allow all ICMP traffic (fourth line in the above table), for pings and traceroutes to succeed)
On Ubuntu images in OCI, we also need to poke holes in iptables on the instance itself:
ubuntu@jekyll:~/jekyllprojects$ sudo iptables -I INPUT -p tcp --dport 8080 -j ACCEPT ubuntu@jekyll:~/jekyllprojects$ sudo iptables -I INPUT -p tcp --dport 4000 -j ACCEPT ubuntu@jekyll:~/jekyllprojects$
Then, connect to http://[instance IP]:8080/ in a browser, and code-server should appear!
Log in with the password in ~/.config/code-server/config.yaml: :bananadance:
I opted not to put Ruby and Jekyll in a Docker container on the instance, but rather just run them natively. Install:
ubuntu@jekyll:~$ sudo apt install -y ruby-full build-essential zlib1g-dev git <SNIP> ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ ruby --version ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [aarch64-linux-gnu] ubuntu@jekyll:~$ gem --version 3.4.20 ubuntu@jekyll:~$
gem install bundler:
ubuntu@jekyll:~$ gem install bundler Fetching bundler-4.0.13.gem ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /var/lib/gems/3.2.0 directory. [SNIP] ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ sudo !! sudo gem install bundler Fetching bundler-4.0.13.gem Successfully installed bundler-4.0.13 Parsing documentation for bundler-4.0.13 Installing ri documentation for bundler-4.0.13 Done installing documentation for bundler after 0 seconds 1 gem installed ubuntu@jekyll:~$
Create a gem installation path in your home dir:
ubuntu@jekyll:~$ cp .bashrc .bashrc.bak.geminstallationpath ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ vi .bashrc ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ diff -U5 .bashrc.bak.geminstallationpath .bashrc --- .bashrc.bak.geminstallationpath 2026-06-04 06:24:47.612806013 +0000 +++ .bashrc 2026-06-04 06:25:32.362218297 +0000 @@ -113,5 +113,9 @@ . /usr/share/bash-completion/bash_completion elif [ -f /etc/bash_completion ]; then . /etc/bash_completion fi fi + +# Ruby gems 2026-06-04 +export GEM_HOME="$HOME/gems" +export PATH="$HOME/gems/bin:$PATH" ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ source .bashrc ubuntu@jekyll:~$
Finally, install Jekyll
ubuntu@jekyll:~$ gem install jekyll [SNIP] Done installing documentation for unicode-display_width, terminal-table, safe_yaml, rouge, forwardable-extended, pathutil, mercenary, liquid, rexml, kramdown, kramdown-parser-gfm, ffi, rb-inotify, rb-fsevent, listen, jekyll-watch, rake, google-protobuf, sass-embedded, jekyll-sass-converter, concurrent-ruby, i18n, http_parser.rb, eventmachine, em-websocket, colorator, base64, public_suffix, addressable, jekyll after 20 seconds 30 gems installed ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ ubuntu@jekyll:~$ jekyll --version jekyll 4.4.1 ubuntu@jekyll:~$
I then git cloned my GitHub Pages repo from GitHub. I never put a Gemfile in my repos, so I did so:
ubuntu@jekyll:~/jekyllprojects/ghprepo$ vi Gemfile ubuntu@jekyll:~/jekyllprojects/ghprepo$ cat Gemfile source "https://rubygems.org" gem "github-pages", group: :jekyll_plugins ubuntu@jekyll:~/jekyllprojects/ghprepo$
And then bundle install:
ubuntu@jekyll:~/jekyllprojects/ghprepo$ bundle install Fetching gem metadata from https://rubygems.org/........... [SNIP] Please ensure that your Gemfiles and .gemspecs are suitably restrictive to avoid an unexpected breakage when 3.0 is released (e.g. ~> 2.3.0). See https://github.com/rubyzip/rubyzip for details. The Changelog also lists other enhancements and bugfixes that have been implemented since version 2.3.0. ubuntu@jekyll:~/jekyllprojects/ghprepo$
To run Jekyll:
ubuntu@jekyll:~/jekyllprojects/ghprepo$ bundle exec jekyll serve --host 0.0.0.0 Configuration file: /home/ubuntu/jekyllprojects/ghprepo/_config.yml To use retry middleware with Faraday v2.0+, install `faraday-retry` gem Source: /home/ubuntu/jekyllprojects/ghprepo Destination: /home/ubuntu/jekyllprojects/ghprepo/_site Incremental build: disabled. Enable with --incremental Generating... done in 1.553 seconds. Auto-regeneration: enabled for '/home/ubuntu/jekyllprojects/ghprepo' Server address: http://0.0.0.0:4000 Server running... press ctrl-c to stop.
And then visit http://[instance IP]:4000/ in your favorite browser. :bananadance:












