├── files ├── supervisor-zerotier.conf └── start.sh ├── config └── route.list ├── docker-compose.yml ├── Dockerfile ├── README.md └── .github └── workflows └── main.yml /files/supervisor-zerotier.conf: -------------------------------------------------------------------------------- 1 | [program:zerotier] 2 | command=zerotier-one 3 | redirect_stdout=false 4 | redirect_stderr=false 5 | -------------------------------------------------------------------------------- /config/route.list: -------------------------------------------------------------------------------- 1 | # format examples: 2 | # space separated 3 | # 192.168.0.0/16 10.144.25.133 4 | # comma separated 5 | # 10.1.0.0/24,10.144.33.242 6 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | zerotier: 5 | image: croc/zerotier 6 | environment: 7 | - NETWORK_ID=9b............34 8 | # - ROUTES=10.10.12.0/23,10.147.20.115;10.10.14.0/23,10.147.20.220 9 | volumes: 10 | - './config/route.list:/config/route.list:ro' 11 | network_mode: host 12 | privileged: true 13 | restart: always 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:focal 2 | 3 | RUN apt-get update && apt-get install -y curl screen supervisor gnupg 4 | RUN curl -L -o /tmp/zerotier-install.sh https://install.zerotier.com/ && bash /tmp/zerotier-install.sh || exit 0 5 | 6 | COPY files/supervisor-zerotier.conf /etc/supervisor/conf.d 7 | COPY files/start.sh /opt/start.sh 8 | RUN chmod 755 /opt/start.sh 9 | 10 | ENTRYPOINT /opt/start.sh 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zerotier 2 | 3 | ## Build 4 | 5 | ``` 6 | docker build -t my/zerotier . 7 | ``` 8 | 9 | ## Preconfig 10 | 11 | You have to load `tun` module on docker host. 12 | 13 | ``` 14 | modprobe tun 15 | ``` 16 | 17 | ## Run 18 | 19 | ``` 20 | docker-compose up -d 21 | ``` 22 | 23 | ## Usage 24 | 25 | ### Create and Connect to network 26 | 27 | 1. ceate a ZeroTier service account on https://my.zerotier.com 28 | 2. create a network on the zerotier's page (You got a Network ID like: 565799d8f6bba354 ) 29 | 3. join the Zerotier node to the network: 30 | ``` 31 | docker-compose exec zerotier zerotier-cli join 565799d8f6bba354 32 | ``` 33 | 4. check "auth" option on the new host line on ZeroTier page 34 | 5. some seconds later, the You got a new zt0 (or something similar) NIC on your docker host, and You can ping other hosts 35 | 36 | You can choose working mode on the web page. If you turn on bridge (mode) on the web site, you can create site2site vpn solution with some ZeroTier nodes easily. 37 | 38 | ### docker-compose way (recommended) 39 | 40 | This way is more quicker and simpler. 41 | 42 | Check my Github page for an example docker-compose.yml file. 43 | 44 | - modify the `NETWORK_ID` 45 | - modify the `ROUTES` and use `,;,;...` if you would like to use Site-to-Site function between the networks. But do not forget to add the routes to your router too (because DHCP clients on LAN use default routes)! 46 | - You can use `config/route.list` files for route rules too. Check the example file for format. 47 | 48 | ``` 49 | docker-compose up -d 50 | ``` 51 | 52 | 53 | Good Luck! 54 | 55 | -------------------------------------------------------------------------------- /files/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #zerotier-one 4 | supervisord -c /etc/supervisor/supervisord.conf 5 | 6 | [ ! -z $NETWORK_ID ] && { sleep 5; zerotier-cli join $NETWORK_ID || exit 1; } 7 | 8 | # waiting for Zerotier IP 9 | # why 2? because you have an ipv6 and an a ipv4 address by default if everything is ok 10 | IP_OK=0 11 | while [ $IP_OK -lt 2 ] 12 | do 13 | ZTDEV=$( ip addr | grep -i zt | grep -i mtu | awk '{ print $2 }' | cut -f1 -d':' ) 14 | echo "Waiting for a ZeroTier IP on $ZTDEV interface... Accept the new host on my.zerotier.com" 15 | IP_OK=$( ip addr show dev $ZTDEV | grep -i inet | wc -l ) 16 | sleep 5 17 | done 18 | 19 | # 20 | # add route rules 21 | # from variable 22 | # 23 | if [ ! -z $ROUTES ] 24 | then 25 | for routeline in $( echo $ROUTES | sed "s@;@\n@g" ) 26 | do 27 | ADDR="$( echo $routeline | cut -f1 -d',' )" 28 | GW="$( echo $routeline | cut -f2 -d',' )" 29 | if [ ! -z $ADDR ] && [ ! -z $GW ] 30 | then 31 | echo "adding route ... $ADDR via $GW" 32 | ip route add "$ADDR" via "$GW" 33 | fi 34 | done 35 | ip route 36 | fi 37 | 38 | # 39 | # add route rules 40 | # from file 41 | # 42 | if [ -e /config/route.list ] 43 | then 44 | echo "Route file found: /config/route.list" 45 | cat config/route.list | while read line 46 | do 47 | for routeline in "$( echo $line | grep -iv '^#' )" 48 | do 49 | # if empty line found - skip this loop 50 | [ -z "$routeline" ] && { continue; } 51 | 52 | ADDR="$( echo $routeline | cut -f1 -d',' | cut -f1 -d' ' )" 53 | GW="$( echo $routeline | cut -f2 -d',' | cut -f2 -d' ' )" 54 | if [ ! -z $ADDR ] && [ ! -z $GW ] 55 | then 56 | echo "adding route ... $ADDR via $GW" 57 | ip route add "$ADDR" via "$GW" 58 | fi 59 | done 60 | done 61 | ip route 62 | fi 63 | 64 | # something that keep the container running 65 | tail -f /dev/null 66 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Auto-CI 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the "master" branch 8 | push: 9 | branches: 10 | pull_request: 11 | branches: [ "master" ] 12 | schedule: 13 | - cron: '00 5 * * 6' # every Sunday at 5:00 14 | 15 | # Allows you to run this workflow manually from the Actions tab 16 | workflow_dispatch: 17 | 18 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 19 | jobs: 20 | # This workflow contains a single job called "build" 21 | build: 22 | # The type of runner that the job will run on 23 | runs-on: ubuntu-latest 24 | 25 | # Steps represent a sequence of tasks that will be executed as part of the job 26 | steps: 27 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 28 | - uses: actions/checkout@v3 29 | 30 | # Runs a set of commands using the runners shell 31 | - name: build container 32 | run: | 33 | # debug 34 | ls -hal 35 | # build container 36 | docker build -t croc/zerotier . 37 | docker images 38 | - name: check and tag version 39 | run: | 40 | docker-compose up -d 41 | echo "waiting for up..." 42 | sleep 5 43 | ZEROTIER_VERSION=$( docker exec -i $( docker-compose images | grep -i zerotier | awk '{ print $1 }' ) zerotier-cli -v ) 44 | echo "Zerotier version: $ZEROTIER_VERSION" 45 | [ -z "$ZEROTIER_VERSION" ] && { echo "Zerotier version NOT FOUND"; exit 1; } 46 | docker tag croc/zerotier croc/zerotier:$ZEROTIER_VERSION 47 | docker images | grep -i zerotier 48 | - name: push container 49 | env: 50 | DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} 51 | DOCKERHUB_PASS: ${{ secrets.DOCKERHUB_PASS }} 52 | run: | 53 | docker images 54 | echo "$DOCKERHUB_PASS" | docker login --username=$DOCKERHUB_USER --password-stdin 55 | docker push croc/zerotier 56 | VERSION=$( docker images | grep -i croc/zerotier | awk '{ print $2 }' | grep -i '^[0-9]' | sort | uniq ) 57 | echo "Image version: $VERSION" 58 | docker push croc/zerotier:$VERSION || { echo "version ($VERSION) image push error - arm64"; exit 1; } 59 | --------------------------------------------------------------------------------