├── Dockerfile ├── README.md ├── docker-compose.yml ├── gcp_instance ├── README.md ├── firewall_rule.json └── vm_instance.json ├── kubernetes ├── 01-namespace.yml ├── 10-service.yml └── 20-deployment.yml └── rootfs └── init /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.19.1 2 | LABEL maintainer="Victor Trac " 3 | 4 | ENV VERSION="1.32.3897.75" 5 | 6 | # Build deps 7 | RUN apk --no-cache add --update go git breezy wget py3-pip \ 8 | gcc python3 python3-dev make musl-dev linux-headers libffi-dev \ 9 | ipset iptables ip6tables openssl-dev py3-dnspython py3-requests \ 10 | py3-setuptools py3-six openssl procps ca-certificates openvpn 11 | 12 | RUN rm /usr/lib/python*/EXTERNALLY-MANAGED \ 13 | && python3 -m ensurepip \ 14 | && pip3 install --no-cache-dir --upgrade pip 15 | 16 | # Install go and deps 17 | COPY --from=golang:1.22-alpine /usr/local/go/ /usr/local/go/ 18 | ENV PATH="/usr/local/go/bin:${PATH}" 19 | 20 | RUN go install github.com/pritunl/pritunl-dns@latest \ 21 | && go install github.com/pritunl/pritunl-web@latest \ 22 | && cp $HOME/go/bin/* /usr/bin 23 | 24 | # Install Pritunl 25 | RUN wget https://github.com/pritunl/pritunl/archive/refs/tags/${VERSION}.tar.gz \ 26 | && tar zxvf ${VERSION}.tar.gz \ 27 | && cd pritunl-${VERSION} \ 28 | && python3 setup.py build \ 29 | && pip3 install -r requirements.txt \ 30 | && mkdir -p /var/lib/pritunl \ 31 | && python3 setup.py install \ 32 | && cd .. \ 33 | && rm -rf *${VERSION}* \ 34 | && rm -rf /tmp/* /var/cache/apk/* 35 | 36 | RUN sed -i -e '/^attributes/a prompt\t\t\t= yes' /etc/ssl/openssl.cnf 37 | RUN sed -i -e '/countryName_max/a countryName_value\t\t= US' /etc/ssl/openssl.cnf 38 | 39 | ADD rootfs / 40 | 41 | EXPOSE 80 42 | EXPOSE 443 43 | EXPOSE 1194 44 | ENTRYPOINT ["/init"] 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pritunl docker 2 | Run Pritunl in a docker container. 3 | 4 | ## Features 5 | 6 | * Based on alpine linux for small images 7 | * Included docker-compose.yml brings mongo (edit it to not expose the mongo port on the host) 8 | 9 | ## Building 10 | export _tag=v1.32.3897.75 11 | docker build -t us-central1-docker.pkg.dev/cloudkite-public/docker-images/pritunl:$_tag . 12 | docker push us-central1-docker.pkg.dev/cloudkite-public/docker-images/pritunl:$_tag 13 | 14 | ## Usage 15 | 16 | git clone https://github.com/cloudkite-io/pritunl-docker 17 | cd pritunl-docker 18 | docker-compose up --build 19 | 20 | The admin console is now available at `https://`, `pritunl`/`pritunl`. 21 | 22 | ## Help 23 | Cloudkite is here to help. Feel free to reach out: https://cloudkite.io 24 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | mongo: 4 | container_name: mongo 5 | image: mongo:4.2.1 6 | networks: 7 | - pritunl 8 | ports: 9 | - "27017:27017" 10 | restart: always 11 | volumes: 12 | - /opt/mongo/data:/data/db 13 | pritunl: 14 | container_name: pritunl 15 | build: . 16 | image: pritunl 17 | depends_on: 18 | - mongo 19 | networks: 20 | - pritunl 21 | ports: 22 | - "80:80" 23 | - "443:443" 24 | - "1194:1194/udp" 25 | privileged: true 26 | restart: always 27 | 28 | networks: 29 | pritunl: 30 | -------------------------------------------------------------------------------- /gcp_instance/README.md: -------------------------------------------------------------------------------- 1 | # GCP instance setup 2 | 3 | * Create a minimal instance at GCP and assign network tag to the instance ([example REST](vm_instance.json)) 4 | 5 | * Configure firewall rule that opens 1194/udp to the instance ([example REST](firewall_rule.json)). 6 | 7 | Helpful links: 8 | * https://cloud.google.com/compute/docs/vpc/firewalls 9 | * https://cloud.google.com/compute/docs/vpc/using-firewalls 10 | -------------------------------------------------------------------------------- /gcp_instance/firewall_rule.json: -------------------------------------------------------------------------------- 1 | { 2 | "allowed": [ 3 | { 4 | "IPProtocol": "udp", 5 | "ports": [ 6 | "1194" 7 | ] 8 | } 9 | ], 10 | "creationTimestamp": "2017-09-07T05:53:53.749-07:00", 11 | "description": "This rule allows ingress packets under the udp protocal at 1194 port", 12 | "direction": "INGRESS", 13 | "id": "1109993682412306318", 14 | "kind": "compute#firewall", 15 | "name": "allow-openvpn-connections", 16 | "network": "projects/cloudkite-dev/global/networks/default", 17 | "priority": 1000, 18 | "selfLink": "projects/cloudkite-dev/global/firewalls/allow-openvpn-connections", 19 | "sourceRanges": [ 20 | "0.0.0.0/0" 21 | ], 22 | "targetTags": [ 23 | "accept-openvpn-connections" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /gcp_instance/vm_instance.json: -------------------------------------------------------------------------------- 1 | { 2 | "canIpForward": false, 3 | "cpuPlatform": "Intel Sandy Bridge", 4 | "creationTimestamp": "2017-09-05T23:06:13.265-07:00", 5 | "description": "", 6 | "disks": [ 7 | { 8 | "autoDelete": true, 9 | "boot": true, 10 | "deviceName": "vpn2-dev", 11 | "index": 0, 12 | "interface": "SCSI", 13 | "kind": "compute#attachedDisk", 14 | "licenses": [ 15 | "projects/debian-cloud/global/licenses/debian-9-stretch" 16 | ], 17 | "mode": "READ_WRITE", 18 | "source": "projects/cloudkite-dev/zones/us-central1-a/disks/vpn2-dev", 19 | "type": "PERSISTENT" 20 | } 21 | ], 22 | "id": "8429699341660335802", 23 | "kind": "compute#instance", 24 | "labelFingerprint": "42WmSpB8rSM=", 25 | "machineType": "projects/cloudkite-dev/zones/us-central1-a/machineTypes/g1-small", 26 | "name": "vpn2-dev", 27 | "networkInterfaces": [ 28 | { 29 | "accessConfigs": [ 30 | { 31 | "kind": "compute#accessConfig", 32 | "name": "External NAT", 33 | "natIP": "104.197.78.21", 34 | "type": "ONE_TO_ONE_NAT" 35 | } 36 | ], 37 | "kind": "compute#networkInterface", 38 | "name": "nic0", 39 | "network": "projects/cloudkite-dev/global/networks/default", 40 | "networkIP": "10.128.0.2", 41 | "subnetwork": "projects/cloudkite-dev/regions/us-central1/subnetworks/default" 42 | } 43 | ], 44 | "scheduling": { 45 | "automaticRestart": true, 46 | "onHostMaintenance": "MIGRATE", 47 | "preemptible": false 48 | }, 49 | "selfLink": "projects/cloudkite-dev/zones/us-central1-a/instances/vpn2-dev", 50 | "serviceAccounts": [ 51 | { 52 | "email": "900621600157-compute@developer.gserviceaccount.com", 53 | "scopes": [ 54 | "https://www.googleapis.com/auth/devstorage.read_only", 55 | "https://www.googleapis.com/auth/logging.write", 56 | "https://www.googleapis.com/auth/monitoring.write", 57 | "https://www.googleapis.com/auth/servicecontrol", 58 | "https://www.googleapis.com/auth/service.management.readonly", 59 | "https://www.googleapis.com/auth/trace.append" 60 | ] 61 | } 62 | ], 63 | "startRestricted": false, 64 | "status": "RUNNING", 65 | "tags": { 66 | "fingerprint": "ifmbRkpF0QE=", 67 | "items": [ 68 | "accept-openvpn-connections", 69 | "http-server", 70 | "https-server" 71 | ] 72 | }, 73 | "zone": "projects/cloudkite-dev/zones/us-central1-a", 74 | "metadata": { 75 | "kind": "compute#metadata", 76 | "fingerprint": "VAlQuShgi50=", 77 | "items": [ 78 | { 79 | "key": "startup-script", 80 | "value": "git clone https://github.com/cloudkite-io/pritunl-docker\ncd pritunl-docker\ndocker-compose up --build" 81 | } 82 | ] 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /kubernetes/01-namespace.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: infrastructure 5 | 6 | -------------------------------------------------------------------------------- /kubernetes/10-service.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: pritunl 5 | namespace: infrastructure 6 | spec: 7 | type: LoadBalancer 8 | ports: 9 | - port: 1194 10 | name: openvpn 11 | protocol: "UDP" 12 | selector: 13 | app: pritunl 14 | 15 | --- 16 | apiVersion: v1 17 | kind: Service 18 | metadata: 19 | name: pritunl-ui 20 | namespace: infrastructure 21 | spec: 22 | type: LoadBalancer 23 | ports: 24 | - port: 80 25 | protocol: "TCP" 26 | targetPort: 80 27 | name: http 28 | - port: 443 29 | targetPort: 443 30 | protocol: "TCP" 31 | name: https 32 | selector: 33 | app: pritunl 34 | 35 | -------------------------------------------------------------------------------- /kubernetes/20-deployment.yml: -------------------------------------------------------------------------------- 1 | apiVersion: extensions/v1beta1 2 | kind: Deployment 3 | metadata: 4 | name: pritunl 5 | namespace: infrastructure 6 | spec: 7 | template: 8 | metadata: 9 | labels: 10 | app: pritunl 11 | spec: 12 | terminationGracePeriodSeconds: 60 13 | containers: 14 | - image: docker.io/victortrac/pritunl 15 | name: pritunl 16 | imagePullPolicy: Always 17 | env: 18 | - name: MONGODB_SERVER 19 | value: "mongodb" 20 | ports: 21 | - containerPort: 80 22 | protocol: TCP 23 | - containerPort: 443 24 | protocol: TCP 25 | - containerPort: 1194 26 | protocol: UDP 27 | securityContext: 28 | privileged: true 29 | -------------------------------------------------------------------------------- /rootfs/init: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pritunl set-mongodb mongodb://${MONGODB_SERVER:-"mongo"}:27017/pritunl 4 | 5 | # get actual port, get value from line and trim spaces 6 | actual_server_port=$(pritunl get app.server_port | cut -d "=" -f2 | awk '{$1=$1};1') 7 | if [[ "$actual_server_port" -ne "${SERVER_PORT:-443}" ]]; then 8 | pritunl set app.server_port ${SERVER_PORT:-443} 9 | fi 10 | 11 | actual_acme_domain=$(pritunl get app.acme_domain | cut -d "=" -f2 | awk '{$1=$1};1') 12 | if [[ ! -z "${ACME_DOMAIN:""}" ]] && [[ "$actual_acme_domain" -ne "${ACME_DOMAIN}" ]] ; then 13 | pritunl set app.acme_timestamp $(date +%s) 14 | pritunl set app.acme_key "$(openssl genrsa 4096)" 15 | pritunl set app.acme_domain ${ACME_DOMAIN} 16 | fi 17 | 18 | pritunl start 19 | --------------------------------------------------------------------------------