Installing code-server on Amazon Lightsail
Overview
code-server lets you access VS Code from a browser at any time. Microsoft’s vscode.dev is a similar option, but it doesn’t support SSH tunneling and you can’t install arbitrary Extensions, so I use code-server instead.
More detail is in the official docs below. This post walks through installing code-server on Amazon Lightsail.
Amazon Lightsail
Amazon Lightsail is AWS’s developer-focused hosting service. It ships pre-configured images so you spend little time setting up the service framework. Amazon EC2 mixes many services together, with granular features suited to building complex architectures; Lightsail is trimmed down and fits small or development-oriented workloads1. Since we’re running VS Code via a browser for development use, Lightsail is a reasonable fit.
Requirements
To install code-server the following are required2. Pick a Lightsail instance that meets at least the minimum:
- 1 GB of RAM
- 2 CPU cores
Install
Install code-server
Once the instance is running, SSH in and install code-server with:
curl -fsSL https://code-server.dev/install.sh | sh
Configure
After installing, edit the config to change the bind address so it’s reachable from outside. Set a login password too.
~/.config/code-server/config.yaml
Change bind-addr and password:
bind-addr: 0.0.0.0:8080
auth: password
password: [your password here]
cert: false
Enable auto-start on reboot
To launch automatically when the server reboots:
sudo systemctl enable --now code-server@$USER
Verify registration:
sudo systemctl list-units code-server@$USER*
You should see something like:
$ sudo systemctl list-units code-server*
UNIT LOAD ACTIVE SUB DESCRIPTION
code-server@ec2-user.service loaded active running code-server
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.
1 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
Restart the service
After registration, restart to actually run the service:
$ sudo service code-server@$USER
Redirecting to /bin/systemctl status code-server@ec2-user.service
● code-server@ec2-user.service - code-server
Dec 22 00:00:53 ip-0... systemd[1]: Started code...
Hint: Some lines were ellipsized, use -l to show in full.
Install Nginx
You can run code-server standalone, but without SSL there are security concerns and some Extensions won’t work properly. So next we install Nginx, attach a dedicated domain, and apply SSL.
If the image doesn’t already have it installed, run:
$ sudo yum install nginx
$ sudo service nginx restart
Configure Nginx
Create the following config file:
/etc/nginx/conf.d/code-server.conf
Edit it like this. Replace {YOUR_DOMAIN} with your domain, and set proxy_pass http://localhost:8080/ to the port code-server is bound to.
server {
listen 80;
server_name {YOUR_DOMAIN};
location / {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
}
}
Once complete, reload Nginx:
$ sudo service nginx reload
The site is now reachable at {YOUR_DOMAIN}.
Nginx password (optional)
code-server already has its own password, so this step is optional. If you want an extra layer of auth at the Nginx level, add htpasswd.
If htpasswd is not installed
$ sudo yum install httpd-tools
Set the password
Replace {YOUR_ID} with your chosen username; the prompt asks for the password:
$ sudo htpasswd -c /etc/nginx/.htpasswd {YOUR_ID}
Add basic auth to the server block
Edit /etc/nginx/conf.d/code-server.conf again:
server {
listen 80;
server_name {YOUR_DOMAIN};
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
}
}
Reload Nginx:
$ sudo service nginx reload
Apply SSL with Let’s Encrypt
Install certbot
To issue a certificate via Let’s Encrypt you need certbot. This assumes the awslinux23 image.
Set up the repository certbot needs:
$ sudo wget -r --no-parent -A 'epel-release-*.rpm' https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
$ sudo rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
$ sudo yum-config-manager --enable epel*
$ sudo yum repolist all
Install certbot:
$ sudo amazon-linux-extras install epel -y
$ sudo yum install certbot python2-certbot-nginx
Configure certbot
Run certbot:
$ sudo certbot
You’ll be asked for your email, the terms of service agreement, and which domain to issue for — pick the one you attached to Nginx.
On success:
Congratulations! You have successfully enabled https://YOUR_DOMAIN
If issuance fails (typically because port 80 is not open externally), open port 80 on Lightsail’s firewall.
Auto-renew via crontab — twice daily is safer, since a missed slot can still succeed on the next run:
39 1,13 * * * root certbot renew --no-self-upgrade
Restart cron
$ sudo systemctl restart crond
What I like
- Almost identical VS Code experience. Anyone used to VS Code can pick it up with no friction.
- Consistent dev environment. Pick up exactly where you left off, which keeps you in flow.
- Works from tablets (iPad, etc.) or anywhere. In particular, SSH works, which opens up a lot more than
vscode.devdoes.
What I don’t like
- Even with Nginx auth, code-server auth, and firewall rules, accessing sensitive servers through it still feels exposed.
- No settings sync, so the initial setup is painful — you re-install every Extension you used before. Support is on the roadmap4.
- Server-side development needs a beefier instance.