Skip to content

Commit

Permalink
Initial setup (#1)
Browse files Browse the repository at this point in the history
* init

* actions

* actions

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* test

* updates

* updates

* clean

* updates

* updates

* lint

* thanks daniel

* port

* port

* port

* port

* ghnyckml

* various gh

* docs and lint

* tests

* tests

* tests

* tests

* tests

* tests

* calculate INTERFACE_NETMASK

* deps

* updates

* updates

* updates

* swap

* updates

* updates

* updates

* firewall

* firewall

* firewall

* firewall

* firewall

* firewall

* deploy

* deploy

* cleanup
  • Loading branch information
james-otten authored Feb 11, 2025
1 parent 63484eb commit c17bc2a
Show file tree
Hide file tree
Showing 29 changed files with 969 additions and 0 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Deploy All Environments
permissions: read-all

on:
push:
branches:
- master
workflow_dispatch:
branches:
- master

jobs:
deploy_dev3:
name: Deploy dev3
uses: ./.github/workflows/deploy_environment.yaml
with:
environment: dev3
varfile: dev.yaml
secrets: inherit
if: github.ref == 'refs/heads/master'

deploy_prod1:
name: Deploy prod1
uses: ./.github/workflows/deploy_environment.yaml
with:
environment: prod1
varfile: wireguard.yaml
secrets: inherit
needs: deploy_dev3
if: github.ref == 'refs/heads/master'
93 changes: 93 additions & 0 deletions .github/workflows/deploy_environment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Deploy VPN Server
permissions: read-all

on:
workflow_call:
inputs:
environment:
required: true
type: string
varfile:
required: true
type: string

env:
# Secrets
TF_VAR_proxmox_host: ${{ secrets.TF_VAR_PROXMOX_HOST }}
TF_VAR_proxmox_token_id: ${{ secrets.TF_VAR_PROXMOX_TOKEN_ID }}
TF_VAR_proxmox_token_secret: ${{ secrets.TF_VAR_PROXMOX_TOKEN_SECRET }}
TF_VAR_local_password: ${{ secrets.TF_VAR_LOCAL_PASSWORD }}
TF_VAR_wg_private_key: ${{ secrets.TF_VAR_WG_PRIVATE_KEY }}
TF_VAR_wg_public_key: ${{ secrets.TF_VAR_WG_PUBLIC_KEY }}
# Credentials for deployment to AWS
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
# S3 bucket for the Terraform state
BUCKET_TF_STATE: ${{ secrets.BUCKET_TF_STATE}}

jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- name: Checkout
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # @v4

- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # @v5
with:
python-version: '3.11'

- name: Setup ansible
run: pip install -r requirements.txt && export PATH="$HOME/.local/bin:$PATH" && ansible-galaxy collection install -r ansible/roles/requirements.yml

- name: Setup Terraform with specified version on the runner
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # @v3
with:
terraform_version: 1.8.3

- name: Setup backend
run: |
echo "bucket = \"${{ secrets.BUCKET_TF_STATE }}\"" > backend.tfvars
echo "key = \"terraform/state/nycmesh-vpn-${{ inputs.environment }}.tfstate\"" >> backend.tfvars
working-directory: ./terraform/

- name: Terraform init
id: init
run: terraform init -backend-config=backend.tfvars
working-directory: ./terraform/

- name: Terraform format
id: fmt
run: terraform fmt -check
working-directory: ./terraform/

- name: Terraform validate
id: validate
run: |
echo "${{ secrets.SSH_PRIVATE_KEY }}" > vpn
echo "${{ secrets.SSH_PUBLIC_KEY }}" > vpn.pub
chmod 600 vpn
chmod 600 vpn.pub
terraform validate
working-directory: ./terraform/

- name: Setup WireGuard
run: |
sudo apt-get update && sudo apt-get install -y wireguard
echo "${{ secrets.WIREGUARD_PRIVATE_KEY }}" > privatekey
sudo ip link add dev wg0 type wireguard
sudo ip address add dev wg0 ${{ secrets.WIREGUARD_OVERLAY_NETWORK_IP }} peer ${{ secrets.WIREGUARD_PEER }}
sudo wg set wg0 listen-port 48123 private-key privatekey peer ${{ secrets.WIREGUARD_PEER_PUBLIC_KEY }} allowed-ips 0.0.0.0/0 endpoint ${{ secrets.WIREGUARD_ENDPOINT }}
sudo ip link set up dev wg0
rm privatekey
- name: Terraform Apply
run: |
terraform apply -auto-approve -input=false -var-file=${{ inputs.environment }}.tfvars
working-directory: ./terraform/

- name: Run playbook
run: |
if [ "wireguard.yaml" != "${{ inputs.varfile }}" ]; then mv "${{ inputs.varfile }}" wireguard.yaml; fi;
export PATH="$HOME/.local/bin:$PATH" && ansible-playbook -i inventory.yaml vpn.yaml
working-directory: ./ansible/
57 changes: 57 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: pull-request

on:
pull_request:

permissions: read-all

env:
BUCKET_TF_STATE: ${{ secrets.BUCKET_TF_STATE}}

jobs:
pull-request:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # @v4

- name: Setup Terraform with specified version on the runner
uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # @v3
with:
terraform_version: 1.8.3

- name: Terraform format
id: fmt
run: terraform fmt -check
working-directory: ./terraform/

- name: Run Checkov action
id: checkov
uses: bridgecrewio/checkov-action@0549dc60bddd4c55cb85c6c3a07072e3cf2ca48e
with:
skip_check: CKV_DOCKER_2,CKV_DOCKER_3,CKV_SECRET_6,CKV2_ANSIBLE_3
quiet: true
output_format: cli,sarif
output_file_path: console,results.sarif
download_external_modules: true

- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3
if: success() || failure()
with:
sarif_file: results.sarif

- name: Run ansible-lint
uses: ansible/ansible-lint@c629b235398065e24ff44b5f1138028642c74a03
with:
args: ""
setup_python: "true"
working_directory: "./ansible/"
requirements_file: ""

- name: Terraform format
run: pip install -r requirements.txt

- name: Run tests
run: ansible-playbook tests.yaml
working-directory: ./ansible/
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
env.sh
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.backup
vpn
vpn.pub
vpn_ed25519
vpn_ed25519.pub
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,46 @@
# vpn-infra

## Adding a config

### Add a road warrior config

1. Generate a public private keypair. `wg genkey | tee yourname_privatekey | wg pubkey > yourname_publickey`
2. Add a new entry to [ansible/wireguard.yaml](./ansible/wireguard.yaml)

| Key | Description | Restrictions |
| ------------- | ------------- | ------------- |
| `NAME` | Name of the interface | Should be letters and numbers |
| `PORT` | Port number for the wireguard interface | Should be a unique number |
| `PEER_PUBLIC_KEY` | Your public key | Should be a wireguard **public** key |
| `INTERFACE_ADDRESS` | Address for the wireguard interface | Should be a unique `/31` in the assigned range (`10.70.250.0/24`). |
| `PEER_ALLOWED_IPS` | IPs allowed to connect. Default `0.0.0.0/0`. | IP range |
| `PEER_PERSISTENT_KEEPALIVE` | Persistent keepalive. Default `25`. | Integer |

3. Open a pull request in this repository with your changes.

4. After your pull request is created, a build will automatically run. If it fails, correct the configuration issue.

5. A volunteer will merge your pull request, you can then [set up your device](https://wiki.nycmesh.net/books/5-networking/page/wireguard-vpn-setup-guide) and start using it.

## Add a remote hub config

1. Generate a public private keypair. `wg genkey | tee nn000_privatekey | wg pubkey > nn000_publickey`
2. Add a new entry to [ansible/wireguard.yaml](./ansible/wireguard.yaml)

| Key | Description | Restrictions |
| ------------- | ------------- | ------------- |
| `NAME` | Name of the interface | Should be nn000 where 000 is your NN |
| `PORT` | Port number for the wireguard interface | Should be a unique number |
| `PEER_PUBLIC_KEY` | Your public key | Should be a wireguard **public** key |
| `INTERFACE_ADDRESS` | Address for the wireguard interface | Should be a unique `/30` in the assigned range (`10.70.250.0/24`). |
| `NEIGHBORS` | Neighbor IP address | An IP address |
| `TX_LENGTH` | MTU. The default is `1420`. | Should be a unique number |
| `COST` | The OSPF cost of the link from the VPN server to your remote hub. The default is `100`. | Should be a unique number |
| `PEER_ALLOWED_IPS` | IPs allowed to connect. Default `0.0.0.0/0`. | IP range |
| `PEER_PERSISTENT_KEEPALIVE` | Persistent keepalive. Default `25`. | Integer |

3. Open a pull request in this repository with your changes.

4. After your pull request is created, a build will automatically run. If it fails, correct the configuration issue.

5. A volunteer will merge your pull request, you can then [set up your device](https://wiki.nycmesh.net/books/5-networking/page/wireguard-vpn-setup-guide) and start using it.
5 changes: 5 additions & 0 deletions ansible/.ansible-lint-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
roles/vpn_mgt/tasks/netfilter.yaml no-changed-when
roles/vpn_mgt/tasks/system_interfaces.yaml no-changed-when
roles/vpn_mgt/tasks/wg_config.yaml no-changed-when
roles/vpn_mgt/tasks/wg_config.yaml yaml[line-length]
tests.yaml yaml[line-length]
26 changes: 26 additions & 0 deletions ansible/dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This is for development only
# Do not use this
#
#
# /$$$$$$$ /$$ /$$ /$$ /$$$$$$$$ /$$
# | $$__ $$ | $$$ | $$ | $$ | $$_____/ | $$
# | $$ \ $$ /$$$$$$ | $$$$| $$ /$$$$$$ /$$$$$$ | $$ /$$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$
# | $$ | $$ /$$__ $$ | $$ $$ $$ /$$__ $$|_ $$_/ | $$$$$ | $$__ $$|_ $$_/ /$$__ $$ /$$__ $$
# | $$ | $$| $$ \ $$ | $$ $$$$| $$ \ $$ | $$ | $$__/ | $$ \ $$ | $$ | $$$$$$$$| $$ \__/
# | $$ | $$| $$ | $$ | $$\ $$$| $$ | $$ | $$ /$$ | $$ | $$ | $$ | $$ /$$| $$_____/| $$
# | $$$$$$$/| $$$$$$/ | $$ \ $$| $$$$$$/ | $$$$/ | $$$$$$$$| $$ | $$ | $$$$/| $$$$$$$| $$
# |_______/ \______/ |__/ \__/ \______/ \___/ |________/|__/ |__/ \___/ \_______/|__/
#
#
#
wireguard_configs:
# For James
- NAME: jameso
PORT: 51822
PEER_PUBLIC_KEY: nj5rB0CIL6JUXLvl+oqQXcav2qnr509FzpF30lF8mEY=
INTERFACE_ADDRESS: "10.70.248.2/31"
# For vpn
- NAME: ghvpn
PORT: 51837
PEER_PUBLIC_KEY: 0vrESEv5ACnVVY20Jzk2na4Twfk+Gk+OMU9rqO6c6AM=
INTERFACE_ADDRESS: "10.70.248.30/31"
3 changes: 3 additions & 0 deletions ansible/inventory.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
plugin: cloud.terraform.terraform_provider
project_path: "../terraform"
9 changes: 9 additions & 0 deletions ansible/roles/requirements.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
collections:
- name: cloud.terraform
version: 3.0.0
- name: nycmesh.common
source: git+https://github.com/nycmeshnet/nycmesh-ansible.git
type: git
version: main
- name: ansible.utils
version: 5.1.2
28 changes: 28 additions & 0 deletions ansible/roles/vpn_mgt/tasks/bird.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
- name: Copy bird.conf
ansible.builtin.template:
src: ./templates/bird.conf.j2
dest: "/etc/bird/bird.conf"
owner: root
group: root
mode: "0644"

- name: IP forward via net.ipv4.ip_forward
ansible.posix.sysctl:
name: net.ipv4.ip_forward
value: '1'
sysctl_set: true
state: present
reload: true

- name: Always restart bird
ansible.builtin.lineinfile:
path: /lib/systemd/system/bird.service
search_string: Restart=
line: "Restart=always"

- name: Restart and enable bird service
ansible.builtin.systemd_service:
name: bird
state: reloaded
enabled: true
daemon_reload: true
53 changes: 53 additions & 0 deletions ansible/roles/vpn_mgt/tasks/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
- name: Install deps
ansible.builtin.apt:
lock_timeout: 240
update_cache: true
pkg:
- ca-certificates
- bird2
- iptables-persistent
- wireguard

- name: Import the mesh_dns role from the nycmesh.common collection
ansible.builtin.import_role:
name: nycmesh.common.mesh_dns
vars:
extra_resolvers: "9.9.9.9"

- name: Import the motd role from the nycmesh.common collection
ansible.builtin.import_role:
name: nycmesh.common.motd
vars:
github_repo: https://github.com/nycmeshnet/vpn-infra

- name: Import the ssh_config role from the nycmesh.common collection
ansible.builtin.import_role:
name: nycmesh.common.ssh_config

- name: SSH only mgt
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
regexp: '^#?\s*ListenAddress\s'
line: 'ListenAddress {{ BIRD_ROUTER_ID }}'
state: present

- name: Restart and enable sshd service
ansible.builtin.service:
name: sshd
state: reloaded
enabled: true

- name: Setup netfilter
ansible.builtin.include_tasks: netfilter.yaml

- name: System interfaces
ansible.builtin.include_tasks: system_interfaces.yaml

- name: Setup Interfaces + Wireguard
ansible.builtin.include_tasks: wg_config.yaml
loop: "{{ wireguard_configs }}"

# Down and drop unused

- name: Setup Bird
ansible.builtin.include_tasks: bird.yaml
11 changes: 11 additions & 0 deletions ansible/roles/vpn_mgt/tasks/netfilter.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
- name: Copy firewall config
ansible.builtin.template:
src: ./templates/netfilter.j2
dest: /etc/iptables/rules.v4
owner: root
group: root
mode: "0600"

- name: Restore firewall rules
ansible.builtin.command:
cmd: "bash -c '/sbin/iptables-restore < /etc/iptables/rules.v4'"
Loading

0 comments on commit c17bc2a

Please sign in to comment.