Learning Server Admin
My journey to run multiple websites on a single VPS using Caddy
At the moment this is less an article and more of a dumping zone for tidbits I would like to include in an article… And since I published it from the start of my website, I’ll leave it here and let it grow.
Goal
Create a server configuration that can host many different project on unique domains.
Reasoning
I have quite a few little hobby projects and hosting them on a per project basis, as most platform as a service hosting require, ends up being complicated and possibly pricy.
If I can configure a single server to host multiple domains and auto deploy from a GitHub action it would fit the workflow I have become accustom to.
The Next Steps
-
- Create a CI workflow to auto deploy projects to the hosting computer from a GitHub action.
-
- Read DevOps for the Desperate and see if it has any helpful hints.
Things that work
- Digital Ocean Server works great and the basic setup guides seem to keep it secure.
- Caddy Server hosting multiple websites with automatic HTTPS cert renewal.
- PM2 kinda works, at the moment the process doesn’t reload on restart and I have to manually do it.
Initial Server Setup
- Initial Server Setup with Ubuntu 18.04
- How To Set Up a Firewall with UFW on Ubuntu 18.04
- How To Harden OpenSSH on Ubuntu 18.04
- How To Install Node.js on Ubuntu 18.04
- How To Set Up a Node.js Application for Production on Ubuntu 18.04
Server Additional Reading
- How to Set Up SSH Keys on Ubuntu 18.04
- Systemd Essentials: Working with Services, Units, and the Journal
Server Maintenance
DNS
Caddy
Setup
- How To Install Go and Set Up a Local Programming Environment on Ubuntu 18.04
- How To Host a Website with Caddy on Ubuntu 18.04
- Cloudflare module for Caddy
Caddyfile
example.com, www.example.com {
reverse_proxy 127.0.0.1:3000
encode gzip
log {
output stderr
format console
level PANIC
}
tls {
dns cloudflare {env.CF_API_TOKEN}
}
}
The CF_API_TOKEN is located in the /etc/systemd/system/caddy.service
...
[Service]
User=caddy
Group=caddy
Environment=CF_API_TOKEN={your_token_here}
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
...
Node.js
Installing Using a PPA
Download the installation script.
cd ~curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh
You can inspect the contents of the script.
nano nodesource_setup.sh
Run the script to install the NodeSource PPA.
sudo bash nodesource_setup.sh
Install Node.js with the package manager.
sudo apt install nodejs
Check that it was installed.
node -v
npm
was also installed.
Because some npm
packages will require compiling code from source, the build-essential
package should also be installed.
sudo apt install build-essential
PM2
PM2 Setup
pm2 start ecosystem.config.js
pm2 save
- run the command generated by
pm2 startup systemd
- inspect the generated unit file
less /etc/systemd/system/pm2-{user_name}.service
sudo systemctl enable pm2-{user_name}
sudo systemctl start pm2-{user_name}
systemctl status pm2-{user_name}
Changing PM2 Configuration After startup
pm2 startOrReload ecosystem.config.js --update-env
This may have resolved the below issue. Just make sure the run pm2 save
afterwards. https://stackoverflow.com/q/44508316
I had a lot of trouble changing the configuration of PM2. Before the changes in the ecosystem.config.js
would be recognized I had to do the following:
pm2 stop all
pm2 delete all
- remove the previously saved configuration
pm2 cleardump
sudo systemctl stop pm2-<USERNAME>
- remove the pm2 service by running the command generated by
pm2 unstartup systemd
sudo systemctl daemon-reload
sudo systemctl reboot
restart the server- Then follow the setup steps
systemd
Users
deploy
app