Pangolin Tunnel Setup Guide#


Current VPS and SSH Access (Verified 2026-08-12)#

The current Pangolin VPS is hosted by RackNerd:

  • VPS hostname: RN-VPS
  • VPS public IP: 72.11.147.220
  • Operating system: Ubuntu
  • SSH port: TCP 22
  • Current home public IP: 208.96.219.86 (may change when the ISP address changes)

SSH access is restricted by multiple layers:

  1. UFW: incoming traffic is denied by default; TCP port 22 is allowed only from the current home public IP.
  2. Fail2ban: the sshd jail has the current home public IP in ignoreip, so it is not accidentally banned. The value must also be present persistently in /etc/fail2ban/jail.local.
  3. CrowdSec: the Pangolin container can enforce decisions through the Ubuntu host firewall via the INPUT and DOCKER-USER iptables chains.

The backup LXC connects outbound to the VPS. It does not require an inbound connection from the VPS to the home network. If the ISP IP changes, update both UFW and Fail2ban before the next backup.

ISP IP Change Procedure#

Run this from a device on the home network, not from the VPS:

curl -4 ifconfig.me

On the VPS, replace the placeholders with the new and old home IPs:

sudo ufw allow from NEW_HOME_IP to any port 22 proto tcp
sudo ufw delete allow from OLD_HOME_IP to any port 22 proto tcp
sudo fail2ban-client set sshd addignoreip NEW_HOME_IP
sudo fail2ban-client set sshd delignoreip OLD_HOME_IP

Update /etc/fail2ban/jail.local so its persistent ignoreip value contains NEW_HOME_IP and does not contain OLD_HOME_IP, then apply it:

sudo fail2ban-client reload

Verify the effective rules:

sudo ufw status verbose
sudo fail2ban-client get sshd ignoreip

Do not use the result of curl -4 ifconfig.me executed on the VPS as the home IP. On the VPS it returns the VPS address (72.11.147.220).


1. Historical Oracle Cloud VPS Instance Setup#

The following Oracle Cloud and Google Cloud sections describe the original setup and are retained as historical reference. The active VPS is the RackNerd instance documented above.

Create VCN (Virtual Cloud Network)#

  1. Name: homeip
  2. IPv4 CIDR Blocks: [REDACTED]
  3. Internet Gateway: Create ig-homeip in Gateways.
  4. Route Rules: Add Route Rule > Target: Internet Gateway > Destination: 0.0.0.0/0.

Create Subnet#

  1. Name: homeip-subnet
  2. IPv4 CIDR Blocks: [REDACTED]
  3. Type: Public Subnet
  4. DNS Label: dns

Create VM Instance#

  1. Name: Pangolin
  2. Image: Ubuntu 24.04
  3. Shape: Ampere VM.Standard.A1.Flex (Always Free-eligible)
  4. Networking: VNIC Name pangolin-vnic. Connect public subnet to internet.
  5. Public IP: [REDACTED]
  6. Username: ubuntu

2. Google Cloud VPS Setup (Alternative)#

  • Region: us-east1 (South Carolina)
  • Machine Type: e2-standard-2
  • Prerequisites: Billing enabled and project created.

3. Cloudflare & Pangolin Installation#

DNS Configuration#

  • Type: A
  • Name: pangolin
  • Content: [REDACTED_SERVER_IP]
  • Proxy status: Off (Grey cloud)

Installation Commands#

# Prepare directory
cd /home/marc/docker-compose
mkdir -p pangolin && cd pangolin
# Download and run installer
curl -fsSL [https://static.pangolin.net/get-installer.sh](https://static.pangolin.net/get-installer.sh) | bash
sudo ./installer

Wildcard Certificates#

Edit the configuration for wildcard domains:

nano /home/marc/docker-compose/pangolin/config/traefik/traefik_config.yaml

4. Crowdsec Management#

Maintenance & Metrics#

# Unban a specific IP
docker exec crowdsec-pangolin cscli decisions delete -i [REDACTED]
# View active decisions and metrics
docker exec crowdsec-pangolin cscli decisions list
docker exec crowdsec-pangolin cscli metrics
docker exec -it crowdsec-pangolin cscli bouncers metrics

Persistent Whitelisting#

  1. Create Whitelist File:
nano /home/marc/docker-compose/pangolin/config/crowdsec/my-whitelist.yaml

Content:

name: whitelist
description: "Trusted IPs"
whitelist:
  reason: "Trusted source"
  ip:
    - [REDACTED]
  1. Update docker-compose.yml: Add to the Crowdsec volumes section:
volumes:
  - ./config/crowdsec/my-whitelist.yaml:/etc/crowdsec/parsers/s02-enrich/my-whitelist.yaml:ro
  1. Verify Whitelist Parsing:
docker exec crowdsec-pangolin cscli parsers list
docker exec -it crowdsec-pangolin sh -c 'grep -R "^[[:space:]]*-" /etc/crowdsec/parsers/s02-enrich/*.yaml'

5. Backups (New Backup Strategy)#

Manual Backups#

# Compress pangolin directory
cd /home/marc/docker-compose
tar -czvf "$(date '+%Y-%m-%d_%Hh%M')_Pangolin.tar.gz" pangolin
# Decompress/Restore
tar -xzvf [BACKUP_FILE_NAME].tar.gz

Automated Cronjobs#

Option 1: Backup with Error Log Only

0 * * * * mkdir -p /home/marc/docker-compose/$(date '+\%Y-\%m-\%d') && tar -czvf "/home/marc/docker-compose/$(date '+\%Y-\%m-\%d')/$(date '+\%Y-\%m-\%d_\%Hh\%M')_Pangolin.tar.gz" /home/marc/docker-compose/pangolin > /dev/null 2>> /home/marc/docker-compose/pangolin_backup_error.log

Option 2: Full Verbose Logging

0 * * * * echo "[$(date '+\%Y-\%m-\%d \%H:\%M:\%S')] Backup started" >> /home/marc/docker-compose/pangolin_backup.log && mkdir -p /home/marc/docker-compose/$(date '+\%Y-\%m-\%d') && tar -czvf "/home/marc/docker-compose/$(date '+\%Y-\%m-\%d')/$(date '+\%Y-\%m-\%d_\%Hh\%M')_Pangolin.tar.gz" /home/marc/docker-compose/pangolin >> /home/marc/docker-compose/pangolin_backup.log 2>&1 && echo "[$(date '+\%Y-\%m-\%d \%H:\%M:\%S')] Backup finished" >> /home/marc/docker-compose/pangolin_backup.log

6. CrowdSec Host Firewall Integration#

To allow the CrowdSec instance inside the Pangolin container to control the Ubuntu host firewall:

Install Firewall Bouncer on Host#

# Add repo and install bouncer
curl -s https://install.crowdsec.net | sudo sh && sudo apt update && sudo apt install -y crowdsec-firewall-bouncer-iptables

# Check status
sudo systemctl status crowdsec-firewall-bouncer
  1. Generate API Key:
docker exec crowdsec-pangolin cscli bouncers add host-bouncer
  1. Configure Bouncer:
sudo nano /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml
  • api_url: Set to http://127.0.0.1:8080/
  • api_key: Paste the key generated in the previous step.
  • iptables_chains: Ensure the following are present to protect Docker containers:
iptables_chains:
  - INPUT
  - DOCKER-USER
  1. Restart and Verify:
sudo systemctl restart crowdsec-firewall-bouncer
docker exec crowdsec-pangolin cscli bouncers list
docker exec crowdsec-pangolin cscli decisions list

7. CrowdSec Hub & Console Management#

Console Integration#

# Connect instance to https://app.crowdsec.net/
docker exec crowdsec-pangolin cscli console enable tainted
docker exec crowdsec-pangolin cscli console enable custom

Hub Update Sequence#

# 1. Download the latest attack signatures
docker exec crowdsec-pangolin cscli hub update

# 2. Upgrade all installed collections (Traefik, SSH, CVEs, etc.)
docker exec crowdsec-pangolin cscli hub upgrade

# 3. Restart the container to apply new rules
docker restart crowdsec-pangolin

# 4. Verify status
docker exec crowdsec-pangolin cscli collections list

Whitelist Management#

  • View Whitelist: docker exec crowdsec-pangolin cat /etc/crowdsec/parsers/s02-enrich/my-whitelist.yaml
  • Modify Whitelist: sudo nano /home/marc/docker-compose/pangolin/config/crowdsec/my-whitelist.yaml
  • Apply Changes: docker restart crowdsec-pangolin

8. Maintenance & Security#

Vulnerability Scanning (Trivy)#

Check all running images for critical vulnerabilities:

docker ps --format "{{.Image}}" | sort -u | xargs -I {} trivy image --severity CRITICAL --quiet --no-progress {}

Traefik Log Rotation#

  1. Check log size:
ls -lh /home/marc/docker-compose/pangolin/config/traefik/logs/
  1. Configure Logrotate:
sudo nano /etc/logrotate.d/traefik

Content: