Install VS Code server on Raspberry Pi.

This software awesome as it works well on Raspberry Pi 3 and 4, so you can code on the go using VPN.

Open releases web-page to download system package.

$ wget https://github.com/coder/code-server/releases/download/v4.9.1/code-server_4.9.1_arm64.deb

Install code-server package.

$ sudo dpkg --install code-server_4.9.1_arm64.deb

Inspect available runtime options.

$ code-server --help
code-server 4.9.1 f7989a4dfcf21085e52157a01924d79d708bcc05 with Code 1.73.1

Usage: code-server [options] [path]
    - Opening a directory: code-server ./path/to/your/project
    - Opening a saved workspace: code-server ./path/to/your/project.code-workspace

Options
      --auth                             The type of authentication to use. [password, none]
      --password                         The password for password authentication (can only be passed in via $PASSWORD or the config file).
      --hashed-password                  The password hashed with argon2 for password authentication (can only be passed in via $HASHED_PASSWORD or the config file).
                                         Takes precedence over 'password'.
      --cert                             Path to certificate. A self signed certificate is generated if none is provided.
      --cert-host                        Hostname to use when generating a self signed certificate.
      --cert-key                         Path to certificate key when using non-generated cert.
      --disable-telemetry                Disable telemetry.
      --disable-update-check             Disable update check. Without this flag, code-server checks every 6 hours against the latest github release and
                                         then notifies you once every week that a new release is available.
      --disable-file-downloads           Disable file downloads from Code. This can also be set with CS_DISABLE_FILE_DOWNLOADS set to 'true' or '1'.
      --disable-workspace-trust          Disable Workspace Trust feature. This switch only affects the current session.
      --disable-getting-started-override Disable the coder/coder override in the Help: Getting Started page.
   -h --help                             Show this output.
      --open                             Open in browser on startup. Does not work remotely.
      --bind-addr                        Address to bind to in host:port. You can also use $PORT to override the port.
      --config                           Path to yaml config file. Every flag maps directly to a key in the config file.
      --socket                           Path to a socket (bind-addr will be ignored).
      --socket-mode                      File mode of the socket.
   -v --version                          Display version information.
      --user-data-dir                    Path to the user data directory.
      --extensions-dir                   Path to the extensions directory.
      --list-extensions                  List installed VS Code extensions.
      --force                            Avoid prompts when installing VS Code extensions.
      --install-extension                Install or update a VS Code extension by id or vsix. The identifier of an extension is `${publisher}.${name}`.
                                         To install a specific version provide `@${version}`. For example: 'vscode.csharp@1.2.3'.
      --enable-proposed-api              Enable proposed API features for extensions. Can receive one or more extension IDs to enable individually.
      --uninstall-extension              Uninstall a VS Code extension by id.
      --show-versions                    Show VS Code extension versions.
      --github-auth                      GitHub authentication token (can only be passed in via $GITHUB_TOKEN or the config file).
      --proxy-domain                     Domain used for proxying ports.
   -e --ignore-last-opened               Ignore the last opened directory or workspace in favor of an empty window.
   -n --new-window                       Force to open a new window.
   -r --reuse-window                     Force to open a file or folder in an already opened window.
 -vvv --verbose                          Enable verbose logging.
  -an --app-name                         The name to use in branding. Will be shown in titlebar and welcome message
   -w --welcome-text                     Text to show on login page
      --link                             (deprecated) Securely bind code-server via our cloud service with the passed name. You'll get a URL like
                                         https://hostname-username.coder.co at which you can easily access your code-server instance.
                                         Authorization is done via GitHub.

Create basic application directories.

$ mkdir -p .code-server/{data,extensions}

Enable user lingering.

$ loginctl enable-linger $USER

Create user related systemd directory.

$ mkdir .config/systemd/user

Create systemd service.

$ tee .config/systemd/user/code-server.service <<EOF
[Unit]
Description=code-server

[Service]
Type=simple
Environment=PASSWORD=random
ExecStart=/usr/bin/code-server --bind-addr 127.0.0.1:8080 --user-data-dir ~/.code-server/data --extensions-dir ~/.code-server/extensions --auth password --disable-telemetry   
Restart=always

[Install]
WantedBy=default.target
EOF

Reload user related systemd configuration.

$ systemctl --user daemon-reload

Start and enable service.

$ systemctl --user enable --now code-server

Inspect service status.

$ systemctl --user status code-server
● code-server.service - code-server
     Loaded: loaded (/home/milosz/.config/systemd/user/code-server.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2022-12-25 01:27:15 CET; 9s ago
   Main PID: 566845 (node)
      Tasks: 22 (limit: 8986)
        CPU: 2.619s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/code-server.service
             ├─566845 /usr/lib/code-server/lib/node /usr/lib/code-server --bind-addr 127.0.0.1:8080 --user-data-dir ~/.code-server/data --extensions-dir ~/.code-server/extensions --auth password --disabl>
             └─566863 /usr/lib/code-server/lib/node /usr/lib/code-server/out/node/entry

Dec 25 01:27:15 raspberrypi systemd[526]: Started code-server.
Dec 25 01:27:17 raspberrypi code-server[566845]: [2022-12-25T00:27:17.281Z] info  code-server 4.9.1 f7989a4dfcf21085e52157a01924d79d708bcc05
Dec 25 01:27:17 raspberrypi code-server[566845]: [2022-12-25T00:27:17.283Z] info  Using user-data-dir ~/~/.code-server/data
Dec 25 01:27:17 raspberrypi code-server[566845]: [2022-12-25T00:27:17.318Z] info  Using config file ~/.config/code-server/config.yaml
Dec 25 01:27:17 raspberrypi code-server[566845]: [2022-12-25T00:27:17.318Z] info  HTTP server listening on http://127.0.0.1:8080/
Dec 25 01:27:17 raspberrypi code-server[566845]: [2022-12-25T00:27:17.318Z] info    - Authentication is enabled
Dec 25 01:27:17 raspberrypi code-server[566845]: [2022-12-25T00:27:17.318Z] info      - Using password from $PASSWORD
Dec 25 01:27:17 raspberrypi code-server[566845]: [2022-12-25T00:27:17.318Z] info    - Not serving HTTPS

Install nginx web-server.

$ sudo apt install nginx

Create SSL certificates (use proper and valid certificates).

$ sudo mkdir /etc/nginx/ssl
$ sudo openssl req -subj "/commonName=code-server.my-network.ts.net/" -x509 -nodes -days 730 -newkey rsa:2048 -keyout /etc/nginx/ssl/certificate.key -out /etc/nginx/ssl/certificate.crt

Remove default configuration.

$ sudo unlink /etc/nginx/sites-enabled/

Create reverse proxy configuration.

$ sudo tee /etc/nginx/sites-enabled/code-server <<'EOF' 
map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}
 
upstream code-server {
  server 127.0.0.1:8080;
}
 
server {
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server;

  server_name _;

  ssl_certificate     /etc/nginx/ssl/certificate.crt;
  ssl_certificate_key /etc/nginx/ssl/certificate.key;


  location / {
    proxy_pass http://code-server;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
  }
}
EOF

Inspect config.

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart nginx service.

$ sudo systemctl restart nginx

Inspect service status and ensure that service is enabled at boot.

$ sudo systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Sun 2022-12-25 01:40:35 CET; 7s ago
       Docs: man:nginx(8)
    Process: 569596 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
    Process: 569598 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
   Main PID: 569599 (nginx)
      Tasks: 5 (limit: 8986)
        CPU: 137ms
     CGroup: /system.slice/nginx.service
             ├─569599 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
             ├─569600 nginx: worker process
             ├─569601 nginx: worker process
             ├─569602 nginx: worker process
             └─569603 nginx: worker process

Dec 25 01:40:35 raspberrypi systemd[1]: Starting A high performance web server and a reverse proxy server...
Dec 25 01:40:35 raspberrypi systemd[1]: Started A high performance web server and a reverse proxy server.
ko-fi