Before deploying your app, make sure it is ready for production .
Tested on Ubuntu 24.04:
- Provision a Linux server (for example, a virtual private server from DigitalOcean or OVH)
- Log in with SSH as default user:
ssh ubuntu@<hostname>
- Update system packages:
sudo apt update && sudo apt upgrade
- Create new user with your name and add it to
sudo
andadm
groups:sudo adduser <username>
andsudo usermod -a -G sudo,adm <username>
- Log out and log in again with the new user
- Delete default user:
sudo deluser --remove-home ubuntu
- Change SSH port to avoid random SSH requests on default port 22
- Log out and log in again on the new port:
ssh <username>@<hostname> -p <port>
- Set up firewall
- Optionally, you can set an SSH key on your local terminal to log in passwordless
To avoid potential performance issues in the future, you can configure memory swap now, or when memory usage starts running high.
- Install dependencies required to run your app (for example with Docker: installation and post-installation)
- Send runtime logs to journald for archival and storage management (for example with Docker: set logging driver and
systemctl restart docker
) - If you plan to fetch source code and build the app on the server itself, install required dependencies (for example: git, make)
- Fetch or build your app executable and start it (do not forget to set environment variables before start, if applicable)
- Make sure app is served locally on the server:
curl http://localhost:<port>
- You can now review app logs:
journalctl CONTAINER_NAME=<docker container name> -f
- Install a web server: Caddy will allow HTTPS requests without any configuration
- Set up reverse proxy in Caddy configuration:
sudo vim /etc/caddy/Caddyfile
- Set up request log output in Caddy configuration
- Update DNS records so that requests to your domain are forwarded to your server (then make sure DNS servers have been updated)
- Reload Caddy :
systemctl reload caddy
- Reboot server (
sudo reboot
) and make sure your web app also restarts (systemd services must be enabled, Docker containers run withrestart: always
) - You can now review Caddy access logs in human-readable format:
journalctl -u caddy --since=today -f -o short-iso | GREP_COLOR='mt=01;33' grep -E --color=always "[0-9]{4}-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]" | grep -E --color=always "\"method[^,]*|\"uri[^,]*" | GREP_COLOR='mt=01;33' grep -P --color=always "\"User-Agent\":\[(.*?)\]"