# Server setup & Deploy Guide
**Audience:** New Ubuntu server (20.04 / 22.04) — quick, safe, repeatable steps to set up a deploy user, N
LTS, Nginx, PM2, UFW, Fail2Ban, Docker (optional), and deploy a Node web app.
---
## 0. Quick notes / assumptions
- You have root / sudo access to the server (or the `ubuntu` default user).
- Replace `YOUR_IP/32`, `USERNAME/[Link]`, and `myapp` with your real values.
- Commands shown should be run as a user with `sudo` or prefixed with `sudo`.
- Files created: `/etc/nginx/sites-available/myapp` (Nginx site).
- App listens on port `3000` by default. Adjust if needed.
---
## 1. System update & essential tools
```bash
sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl wget build-essential software-properties-common apt-transport-https ca-certificat
es
```
---
## 2. Create `deploy` user (with same SSH keys as ubuntu)
```bash
# create user and add to sudo
sudo adduser --disabled-password --gecos "" deploy
sudo usermod -aG sudo deploy
# copy SSH keys from ubuntu (if present)
sudo mkdir -p /home/deploy/.ssh
sudo cp /home/ubuntu/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
```
---
## 3. Install Node (LTS), npm and verify
```bash
# NodeSource LTS installer
curl -fsSL [Link] | sudo -E bash -
sudo apt install -y nodejs
# verify versions
node -v
npm -v
```
---
## 4. PM2 process manager (run apps as deploy user)
```bash
sudo npm install -g pm2
# enable pm2 startup for deploy user (sets systemd service)
sudo -i -u deploy bash -c "pm2 startup systemd -u deploy --hp /home/deploy"
```
After you start processes with pm2 as `deploy`, run `pm2 save` to persist list.
---
## 5. Install and enable Nginx
```bash
sudo apt install -y nginx
sudo systemctl enable --now nginx
sudo nginx -t
sudo systemctl reload nginx
```
Create Nginx site config `/etc/nginx/sites-available/myapp`:
```nginx
server {
listen 80;
server_name _;
location / {
proxy_pass [Link]
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
```
Enable and reload:
```bash
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
sudo nginx -t
sudo systemctl reload nginx
```
---
## 6. Firewall (UFW) & Fail2Ban
```bash
sudo apt install -y ufw fail2ban
# Allow only necessary services
# If you can, restrict SSH to your IP: sudo ufw allow from YOUR_IP/32 to any port 22
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw --force enable
sudo ufw status verbose
sudo systemctl enable --now fail2ban
```
---
## 7. Optional: Docker install & add deploy to docker group
```bash
curl -fsSL [Link] -o [Link]
sudo sh [Link]
sudo usermod -aG docker deploy
# Log out and log in again (or reboot) to apply group change
```
---
## 8. Prepare web root and clone repo (as deploy)
```bash
sudo mkdir -p /var/www/myapp
sudo chown -R deploy:deploy /var/www/myapp
# as deploy user, clone repo into /var/www
sudo -i -u deploy bash -c "cd /var/www && git clone [Link] myapp || true"
# or use SSH:
# sudo -i -u deploy bash -c "cd /var/www && git clone git@[Link]:USERNAME/[Link] myapp"
```
---
## 9. Install app deps, build and run (example Node app)
```bash
cd /var/www/myapp
# if repository has [Link]:
npm install
# optional build step
npm run build
# start with pm2 (as deploy user)
pm2 start [Link] --name myapp # or: pm2 start npm --name myapp -- start
pm2 save
# ensure startup already configured earlier; if not:
pm2 startup systemd -u deploy --hp /home/deploy
```
Check pm2 list:
```bash
pm2 list
pm2 logs myapp
```
---
## 10. Serve static site (optional simple move to /var/www/html)
If your repo contains a static `[Link]` and you prefer Nginx serve static:
```bash
sudo rm -f /var/www/html/[Link]
sudo cp /var/www/myapp/[Link] /var/www/html/[Link]
sudo systemctl restart nginx
```
---
## 11. Common maintenance commands
```bash
# update system
sudo apt update && sudo apt upgrade -y
# restart nginx
sudo systemctl restart nginx
# restart node app via pm2
pm2 restart myapp
pm2 stop myapp
pm2 delete myapp
# update code & restart
cd /var/www/myapp
git pull
npm install
pm2 restart myapp
```
---
## 12. Troubleshooting tips
- Nginx 502 or 504: ensure your app is running on the proxied port (3000). Check `pm2 logs`.
- Permission errors: ensure `/var/www/myapp` is owned by `deploy:deploy`.
- SSH access issues: check `/var/log/[Link]` and UFW rules.
- pm2 service not starting on reboot: rerun the `pm2 startup ...` command as deploy, then `pm2 save`.
---
## 13. Security checklist before going public
- Restrict SSH to your IP (UFW).
- Use SSH keys; disable password login in `/etc/ssh/sshd_config`.
- Obtain TLS cert (Let's Encrypt) with certbot:
```bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d [Link]
```
- Keep the server updated regularly.
---
## 14. Example full run (copy-paste, adapt values)
```bash
sudo apt update && sudo apt upgrade -y
sudo adduser --disabled-password --gecos "" deploy
sudo usermod -aG sudo deploy
sudo mkdir -p /home/deploy/.ssh
sudo cp /home/ubuntu/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chmod 600 /home/deploy/.ssh/authorized_keys
sudo apt install -y git curl wget build-essential ufw fail2ban nginx
curl -fsSL [Link] | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g pm2
sudo -i -u deploy bash -c "pm2 startup systemd -u deploy --hp /home/deploy"
# Nginx site file creation (use heredoc as root)
sudo tee /etc/nginx/sites-available/myapp <<'EOF'
server {
listen 80;
server_name _;
location / {
proxy_pass [Link]
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
EOF
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
sudo nginx -t
sudo systemctl reload nginx
# UFW
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw --force enable
# Clone & start app
sudo mkdir -p /var/www/myapp
sudo chown -R deploy:deploy /var/www/myapp
sudo -i -u deploy bash -c "cd /var/www && git clone [Link] myapp || true"
sudo -i -u deploy bash -c "cd /var/www/myapp && npm install && pm2 start [Link] --name myapp && pm2 s
```
---
## 15. Appendices
- Useful commands: `ss -tulpn` (check listening ports), `journalctl -u nginx -b` (nginx logs), `sudo tail -n 2
00 /var/log/syslog`.
- Replace `USERNAME/[Link]` with your repo, and `YOUR_IP/32` with your IP when restricting SSH.
---
**End of guide**