To deploy my Next.js app to my local Debian server while still having my domain point to it, I had to first enable port forwarding on my router. I forwarded 80 to 80 and 443 to 443. Don't do what some guides say and do 80 to 3000, I can't remember why, but I think it had something to do with nginx.
I had to enable some ports through my `ufw` firewall, I don't really remember which. I think one was `sudo ufw allow 'Nginx Full'`. Then `sudo ufw reload`.
Speaking of, BEFORE STARTING THE NEXTJS app, go ahead and get nginx setup.
This is what my `/etc/nginx/sites-available/nextjs-app` looked like:
```
server {
server_name mydomain.com www.mydomain.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
}
```
Then link it with `sudo ln -s /etc/nginx/sites-available/nextjs-app /etc/nginx/sites-enabled/`. Test with `sudo nginx -t`. Restart with `sudo systemctl restart nginx`.
I made sure my DNS records were set up to point to my IP:
- Host: @, Type: A, Data: MY_IP_ADDRESS
- Host: www, Type: www, Data: MY_IP_ADDRESS
Then I ran `sudo certbot --nginx`.
This would automatically update my nginx file to accept SSL, but after that I changed it to work with Next.js. This is what it looked like after certbot and the NextJS addition:
```
server {
server_name mydomain.com www.mydomain.com;
location / {
proxy_pass http://localhost:3000;
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;
}
location /.well-known/acme-challenge/ {
root /var/www/html;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
```
Then when I had a built version of my app on the server, I ran `pm2 start yarn --name "app_name" -- start` from within the app directory. You can set it to always start on server boot with `pm2 startup`. Then save with `pm2 save`. Now I can do like `pm2 start app_name`, `pm2 stop app_name`, `pm2 restart app_name`, and `pm2 reload app_name` (last one is supposedly zero downtime).
After this, I was able to access my app at https://mydomain.com.
_9.2.2024_
I then wanted to deploy a second app to my server, using the subdomain example.anotherdomain.com.
In order to do this, I added a new A record in Cloudflare:
```
Host: example
Type: A
Data: MY_IP_ADDRESS
```
I cloned the repo I wanted to run to my server, and started it with:
```bash
pm2 start yarn --name "second_example_app" -- start
pm2 startup
pm2 save
```
Then I had to create a new Nginx server block:
```bash
sudo nano /etc/nginx/sites-available/example.anotherdomain.com
```
Where I put:
```
server {
server_name example.anotherdomain.com;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
proxy_pass http://localhost:3001;
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;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.anotherdomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.anotherdomain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = example.anotherdomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name example.anotherdomain.com;
return 404; # managed by Certbot
```
Then I enabled the server block with:
```bash
sudo ln -s /etc/nginx/sites-available/example.anotherdomain.com /etc/nginx/sites-enabled
```
Tested with:
```bash
sudo nginx -t
```
Reloaded nginx:
```bash
sudo systemctl reload nginx
```
Got the SSL certificate:
```bash
sudo certbot --nginx -d example.anotherdomain.com
```
Restarted the app for good measure:
```bash
pm2 restart second_example_app
```
_12.1.2024_
I make no promises as to the security of either of these methods. If there are glaring vulnerabilities or easy ways to harden these, please shoot me an email at [
[email protected]](mailto:
[email protected]).