On the internet a VPN can mean two things.
- You had purchased some VPN subscription to use where ever to make a direct secure connection to an Internet Entry point where on the globe.
- You have a vpn to your home/work location enable your local network on your roaming device.
This is Both.
This git describes and utilizes a VPN Connection to a home network with a secure VPN Connection to the internet.
Somewhere -> VPN -> Localnetwork -> VPN -> Some anonymous gateway.
This project provides a solution for securely connecting to your home network (Local LAN) while routing all outgoing traffic through a secure VPN gateway.
For a detailed overview of what changed in this repository, see the Changelog.
Important
View the Architecture Pipelines for a visual overview of the infrastructure:
- Inbound: Connect to your home from anywhere (Roaming).
- Outbound: Your traffic leaves your home via an anonymized VPN tunnel.
Path: Roaming Device -> Incoming VPN -> Local Network -> VPN Gateway -> Anonymous Exit Node
A modern PHP dashboard to monitor status and switch between VPN profiles.

The current dashboard and login flow are documented below.
Better use Home assistant to get information.
two Machines are uses to create this setup. VpnGateway and incomingVpnServer.
The web control center is available at http://localhost:8080 when you run the gateway container locally.
Default fallback credentials in code are only meant for first-run local testing:
- Username: login
- Password: pass
Use the automated local stack setup to generate your own local credentials and bring up both VPN containers:
./scripts/setup-local-vpn.shThis creates .env.local (not committed), writes runtime tunnel configs under .runtime/, starts both containers, and activates the localtest tunnel profile.
If you need manual overrides, use environment variables:
docker rm -f securevpn-gateway-local >/dev/null 2>&1 || true
docker run -d \
--name securevpn-gateway-local \
-p 8080:80 \
-e VPN_ADMIN_USERNAME=mydevuser \
-e VPN_ADMIN_PASSWORD='Use-A-Strong-Temp-Password' \
securevpn-gateway:localUse a password hash in production and avoid plain-text credentials.
- Generate a bcrypt hash:
php -r "echo password_hash('YourStrongPassword', PASSWORD_BCRYPT, ['cost' => 12]) . PHP_EOL;"- Start or update the gateway with hashed credentials:
docker rm -f securevpn-gateway-local >/dev/null 2>&1 || true
docker run -d \
--name securevpn-gateway-local \
-p 8080:80 \
-e VPN_ADMIN_USERNAME=myuser \
-e VPN_ADMIN_PASSWORD_HASH='$2y$12$replace_with_real_hash' \
securevpn-gateway:local- Store secrets outside version control, for example in a non-committed env file.
For local production-like Docker runs, use .env.local with strict file permissions (chmod 600) and recreate containers after credential updates.
When you rotate credentials, recreate the container with new values and verify health:
docker inspect --format='{{.State.Health.Status}}' securevpn-gateway-localRun the verification script after startup to confirm tunnel activation:
./scripts/verify-local-vpn.shExpected result includes:
ActiveState=active- active profile name (for example
localtest) - confirmation that
tun0exists in the gateway container
Sensitive and runtime-generated files are intentionally ignored from version control:
.runtime/(generated keys and local test configs).envand.env.*(credential files)*.key,*.pem,*.p12,*.ovpn
Keep secrets in ignored local files only and never commit generated keys.
The routing inteligence is the following Iptable/IP rule:
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
ip route add 10.8.0.0/24 dev tun0 table 11
ip route add default via VpnGateway dev eth0 table 11
ip rule add from 10.8.0.0/24 table 11
ip rule add to 10.8.0.0/24 table 11
for this you require an VPN hosting using openvpn
- place working not asking for password openvpn configurations in the folder /etc/openvpn/clientConfig
auth-user-pass /etc/openvpn/password.txt
- install the vpnadmin.sh to /usr/bin/local and grant it passwordless sudo for the www-data user
- copy /etc/rsyslog.d/openvpn.conf
- install a webserver
- copy the php site. !change the hardcoded username/password
- systemctl enable openvpn@client.conf
now vpnadmin should work.
- install a openvpn server. (or wireguard) I recommend use a script like https://www.pivpn.io/ Stop here if you want to use ip-switcher.
- copy the up.sh script to /etc/openvpn/
- edit the up script you your local ip settings
- apply
script-security 3
up /etc/openvpn/up.sh
to the server.conf



