---
# System prepended metadata

title: 'Complete Guide: FRP, Nginx, Certbot, and WireGuard Setup'
tags: [AWS, AmazonLinux]

---

:::info
Please refer to [No-IP auto update](https://hackmd.io/rK8zrvuKRi6LBuAviBLS9Q) for automatic updating No-IP hostname.
:::

# Complete Guide: FRP, Nginx, Certbot, and WireGuard Setup

This guide provides step-by-step instructions to set up:
- **FRP (Fast Reverse Proxy)** for NAT traversal.
- **Nginx** with **Certbot** for HTTPS.
- **WireGuard** on Raspberry Pi OS 64-bit using PiVPN.
- Additional configurations for SSH forwarding and more.

---
[TOC]
---
## Prerequisites

1. **EC2 Instance (Amazon Linux 2):**
   - Public IP and domain name (`ec2-cwbw.ddns.net`).
   - Ports opened: `80 (HTTP)`, `443 (HTTPS)`, `2222 (SSH forwarding)`, `7000 (FRP)`, `8484 (GameServer)`, `8585 (GameServer)`, `8586 (GameServer)`, `8596 (GameServer)`, `51820 (WireGuard VPN (UDP))`.
   ![ModifyInboundSecurityGroupRules _ EC2 _ ap-northeast-1](https://hackmd.io/_uploads/BkALmVOPyg.jpg)

2. **MyHomeServer (Raspberry Pi OS 64-bit):**
   - No public IP.
   - Services running on ports: `22 (SSH)`, `8080 (HTTP)`, `8081 (HTTP)`, `8484 (GameServer)`, `8585 (GameServer)`, `8586 (GameServer)`, `8596 (GameServer)`, `51820 (WireGuard VPN (UDP))`.

3. **FRP Version:** `0.61.1`.

---

## Step 1: Install and Configure FRP

### On EC2 (FRP Server):

1. **Download and Install FRP:**
   ```bash
   cd ~
   wget https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_amd64.tar.gz
   tar -zxvf frp_0.61.1_linux_amd64.tar.gz
   cd frp_0.61.1_linux_amd64
   ```

2. **Configure FRP Server (`~/frp_0.61.1_linux_amd64/frps.ini`):**
   ```ini
   [common]
   bind_port = 7000
   ```

3. **Set Up FRP as a Systemd Service:**
   - Create a systemd service file:
     ```bash
     sudo nano /etc/systemd/system/frps.service
     ```
   - Add the following content:
     ```ini
     [Unit]
     Description=FRP Server
     After=network.target

     [Service]
     User=ec2-user
     WorkingDirectory=/home/ec2-user/frp_0.61.1_linux_amd64
     ExecStart=/home/ec2-user/frp_0.61.1_linux_amd64/frps -c /home/ec2-user/frp_0.61.1_linux_amd64/frps.ini
     Restart=always
     RestartSec=5

     [Install]
     WantedBy=multi-user.target
     ```
   - Reload systemd and start the service:
     ```bash
     sudo systemctl daemon-reload
     sudo systemctl start frps
     sudo systemctl enable frps
     ```

---

### On MyHomeServer (FRP Client):

1. **Download and Install FRP:**
   ```bash
   cd ~
   wget https://github.com/fatedier/frp/releases/download/v0.61.1/frp_0.61.1_linux_arm64.tar.gz
   tar -zxvf frp_0.61.1_linux_arm64.tar.gz
   cd frp_0.61.1_linux_arm64
   ```

2. **Configure FRP Client (`~/frp_0.61.1_linux_arm64/frpc.ini`):**
   ```ini
   [common]
   server_addr = {EC2_PUBLIC_IP}
   server_port = 7000
   
   [ssh_forwarding]
   type = tcp
   local_port = 22
   remote_port = 2222

   [http_8080]
   type = tcp
   local_port = 8080
   remote_port = 8080

   [http_8081]
   type = tcp
   local_port = 8081
   remote_port = 8081

   [game_8484]
   type = tcp
   local_port = 8484
   remote_port = 8484

   [game_8585]
   type = tcp
   local_port = 8585
   remote_port = 8585

   [game_8586]
   type = tcp
   local_port = 8586
   remote_port = 8586
   
   [game_8596]
   type = tcp
   local_port = 8596
   remote_port = 8596

   [wireguard_51820]
   type = udp
   local_port = 51820
   remote_port = 51820
   ```

3. **Set Up FRP as a Systemd Service:**
   - Create a systemd service file:
     ```bash
     sudo nano /etc/systemd/system/frpc.service
     ```
   - Add the following content:
     ```ini
     [Unit]
     Description=FRP Client
     After=network.target

     [Service]
     User=pi
     WorkingDirectory=/home/pi/frp_0.61.1_linux_arm64
     ExecStart=/home/pi/frp_0.61.1_linux_arm64/frpc -c /home/pi/frp_0.61.1_linux_arm64/frpc.ini
     Restart=always
     RestartSec=5

     [Install]
     WantedBy=multi-user.target
     ```
   - Reload systemd and start the service:
     ```bash
     sudo systemctl daemon-reload
     sudo systemctl start frpc
     sudo systemctl enable frpc
     ```

---

## Step 2: Install Nginx and Certbot on EC2

### 1. **Install Nginx:**
   ```bash
   sudo yum install nginx -y
   ```

### 2. **Start and Enable Nginx:**
   ```bash
   sudo systemctl start nginx
   sudo systemctl enable nginx
   ```

### 3. **Install Certbot:**
   ```bash
   sudo yum install certbot python3-certbot-nginx -y
   ```

### 4. **Obtain SSL Certificate:**
   Run Certbot to obtain the SSL certificate and configure Nginx for HTTPS:
   ```bash
   sudo certbot --nginx -d ec2-cwbw.ddns.net
   ```
   - Certbot will:
     1. Temporarily spin up a web server to validate your domain ownership.
     2. Obtain the SSL certificate from Let’s Encrypt.
     3. Modify your Nginx configuration to include the certificate and set up HTTPS.

### 5. **Complete Nginx Configuration:**
   After Certbot has configured SSL, you can safely edit your Nginx configuration (`/etc/nginx/nginx.conf`) to add custom settings (e.g., reverse proxy rules for `8080` and `8081`).

   Example configuration:
   ```nginx
   user nginx;
   worker_processes auto;
   error_log /var/log/nginx/error.log;
   pid /run/nginx.pid;

   events {
       worker_connections 1024;
   }

   http {
       include /etc/nginx/mime.types;
       default_type application/octet-stream;

       log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                       '$status $body_bytes_sent "$http_referer" '
                       '"$http_user_agent" "$http_x_forwarded_for"';

       access_log /var/log/nginx/access.log main;

       sendfile on;
       keepalive_timeout 65;

       server {
           listen 80;
           server_name ec2-cwbw.ddns.net;

           # Redirect all HTTP requests to HTTPS
           return 301 https://$host$request_uri;
       }

       server {
           listen 443 ssl;
           server_name ec2-cwbw.ddns.net;

           # SSL certificates (added by Certbot)
           ssl_certificate /etc/letsencrypt/live/ec2-cwbw.ddns.net/fullchain.pem;
           ssl_certificate_key /etc/letsencrypt/live/ec2-cwbw.ddns.net/privkey.pem;

           # SSL settings
           ssl_protocols TLSv1.2 TLSv1.3;
           ssl_ciphers HIGH:!aNULL:!MD5;
           ssl_prefer_server_ciphers on;

           # Proxy for 127.0.0.1:8080
           location /8080/ {
               proxy_pass http://127.0.0.1:8080/;
               proxy_set_header Host $host;
               proxy_set_header X-Real-IP $remote_addr;
               proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
               proxy_set_header X-Forwarded-Proto $scheme;
           }

           # Proxy for 127.0.0.1:8081
           location /8081/ {
               proxy_pass http://127.0.0.1:8081/;
               proxy_set_header Host $host;
               proxy_set_header X-Real-IP $remote_addr;
               proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
               proxy_set_header X-Forwarded-Proto $scheme;
           }

           # Security headers
           add_header X-Frame-Options "SAMEORIGIN";
           add_header X-Content-Type-Options "nosniff";
           add_header X-XSS-Protection "1; mode=block";
       }
   }
   ```

6. **Reload Nginx:**
   ```bash
   sudo systemctl reload nginx
   ```

---

## Step 3: Automate Certbot Certificate Renewal

Certbot typically sets up a cron job in `/etc/cron.d/certbot` to automatically renew certificates. Here’s how to verify and set it up:

### 1. **Check for the Certbot Cron Job:**
   ```bash
   cat /etc/cron.d/certbot
   ```
   - If you see a line like this, the cron job is already set up:
     ```
     0 0,12 * * * root /usr/bin/certbot renew --quiet
     ```
   - If the file doesn’t exist or is empty, proceed to the next step.

### 2. **Add the Certbot Cron Job (if missing):**
#### Ubuntu
   ```bash
   sudo nano /etc/cron.d/certbot
   ```
#### Amazon Linux
   ```bash
   sudo crontab -e
   ```
   Add the following line:
   ```
   0 0,12 * * * root /usr/bin/certbot renew --quiet
   ```
   - This cron job runs twice a day (at midnight and noon) to check if the certificate needs renewal.
   - The `--quiet` flag ensures Certbot doesn’t produce unnecessary output.

### 3. **Test the Renewal Process:**
   ```bash
   sudo certbot renew --dry-run
   ```
   - If the dry run succeeds, the cron job will work as expected.
   - If it fails, check the logs for errors:
     ```bash
     sudo journalctl -u certbot
     ```

---

## Step 4: Install WireGuard on Raspberry Pi OS 64-bit

1. **Install PiVPN:**
   ```bash
   curl -L https://install.pivpn.io | bash
   ```

2. **Follow the PiVPN Wizard:**
   - Select `WireGuard` as the VPN protocol.
   - Configure the VPN settings as needed.

3. **Start WireGuard:**
   ```bash
   sudo systemctl start wg-quick@wg0
   sudo systemctl enable wg-quick@wg0
   ```

---

## Step 5: Verify the Setup

1. **Access Services:**
   - HTTP/HTTPS: `https://ec2-cwbw.ddns.net:8080/` and `https://ec2-cwbw.ddns.net:8081/`.
   - Game Servers: Use the respective ports (`8484`, `8585`, `8586`, `8596`) on the EC2 public IP.
   - WireGuard: Connect to `ec2-cwbw.ddns.net:51820`.
   - SSH: Use `ec2-cwbw.ddns.net:2222` to access MyHomeServer SSH.
       - Example `.ssh/config`
            ```
            Host rpi4-ec2-cwbw
            HostName ec2-cwbw.ddns.net
            port 2222
            User pi
            PreferredAuthentications publickey
            IdentityFile /Users/brad/.ssh/rpi4
            ServerAliveInterval 60
            ServerAliveCountMax 3
            TCPKeepAlive yes
            ```

2. **Test FRP:**
   - Ensure all forwarded ports are accessible.

---

## Step 6: Add More Ports to FRP

To add more ports, edit the `frpc.ini` file on MyHomeServer and add new sections. For example:
```ini
[custom_port_9000]
type = tcp
local_port = 9000
remote_port = 9000
```

Restart the FRP client:
```bash
sudo systemctl restart frpc
```

---

## Conclusion

You now have a fully functional setup with:
- FRP for NAT traversal.
- Nginx with Certbot for HTTPS.
- WireGuard for secure VPN access.
- Additional configurations for SSH and more.
