├── .gitignore ├── README.md ├── ansible.cfg ├── build.yml ├── configure.yml ├── hosts ├── initial_setup.yml └── roles ├── apache ├── files │ ├── Dockerfile │ └── httpd-foreground └── tasks │ └── main.yml ├── auth ├── tasks │ └── main.yml └── templates │ └── httpd.conf.j2 ├── registry ├── files │ └── Dockerfile └── tasks │ └── main.yml ├── setup ├── handlers │ └── main.yml ├── tasks │ └── main.yml └── templates │ └── zshrc.j2 └── start └── tasks └── main.yml /.gitignore: -------------------------------------------------------------------------------- 1 | *.retry 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # registry-pi 2 | 3 | Docker Registry on a Raspberry Pi. 4 | 5 | Tested on Raspberry Pi 3. 6 | 7 | ## Background 8 | 9 | If you have a group of 40 or more people in one room with limited bandwidth, everyone trying to pull Dockerimages from Docker Hub, you are going to have a bad time. 10 | 11 | You can set up a registry proxy or a private registry locally to alleviate the network. This can be done relatively easily on a laptop, so why bother with a Raspberry Pi? 12 | 13 | * Portable (you can keep it in your jacket pocket) 14 | * Energy efficient (runs on 5 V so you can use a regular phone charger) 15 | * Low cost (you don't have to buy a $300 laptop) 16 | * It's fun :smile: 17 | 18 | ## Overview 19 | 20 | ### DNS 21 | 22 | Follow the setup in [local-registry](https://github.com/docker-oxford/local-registry) for keys and a trusted DNS. 23 | 24 | If you don't set up DNS and real certificates, you can still use your registry, but you'll have to tell everyone using it to add `--insecure-registry ip.or.hostname:port` to `/etc/defaults/docker` and restart the Docker Engine. That will completely disable security for any interaction with your registry, and may (will) cause (various) problems with authentication later on. This guide assumes that you have a real DNS name and a signed certificate to prove it. 25 | 26 | ### OS 27 | 28 | [Hypriot OS](http://blog.hypriot.com/downloads/) lets you run Docker on the pi. 29 | 30 | ### Registry 31 | 32 | We will build the registry for ARM with `hypriot/rpi-golang` as the base image. 33 | 34 | ### Web server 35 | 36 | We'll use the web server setup from the [official documentation](https://docs.docker.com/registry/apache/), but alter it slightly to work on pi. This will let us restrict pushing of images to an admin user. 37 | 38 | # Setting it up 39 | 40 | ## Preparations 41 | 42 | Before you begin, ensure that you have the latest versions of [Ansible](http://www.ansible.com) and [Docker](http://www.docker.com) on your local machine. 43 | 44 | ## OS installation 45 | 46 | *Time required: 5 min* 47 | 48 | Tested on Mac. The steps will be similar on Linux (PRs welcome for Linux steps). 49 | 50 | ## NOTE: You are responsible for your own data. This tutorial assumes that you have made recent backups of your laptop and other devices, that you are using a blank SD card or are happy to erase all data on it. The author does not take responsibility for any data loss incurred by following any advice given in this document. 51 | 52 | # Download Hypriot OS 53 | wget https://downloads.hypriot.com/hypriot-rpi-20160306-192317.img.zip 54 | 55 | # Unzip image file 56 | unzip hypriot-rpi-20160306-192317.img.zip 57 | 58 | # Insert an SD card 59 | # List all disks 60 | diskutil list 61 | /dev/disk0 (internal, physical): 62 | #: TYPE NAME SIZE IDENTIFIER 63 | 0: GUID_partition_scheme 251.0 GB disk0 64 | 1: EFI EFI 209.7 MB disk0s1 65 | 2: Apple_CoreStorage Macintosh HD 250.1 GB disk0s2 66 | 3: Apple_Boot Recovery HD 650.1 MB disk0s3 67 | /dev/disk1 (internal, virtual): 68 | #: TYPE NAME SIZE IDENTIFIER 69 | 0: Apple_HFS Macintosh HD +249.8 GB disk1 70 | Logical Volume on disk0s2 71 | 12345678-ABCD-1234-EFAB-1234567890AB 72 | Unlocked Encrypted 73 | /dev/disk5 (internal, physical): 74 | #: TYPE NAME SIZE IDENTIFIER 75 | 0: FDisk_partition_scheme 31.1 GB disk5 76 | 1: Windows_FAT_16 RECOVERY 1.2 GB disk5s1 77 | 2: Linux 33.6 MB disk5s5 78 | 3: Windows_FAT_32 boot 66.1 MB disk5s6 79 | 4: Linux 29.8 GB disk5s7 80 | 81 | # Erase the SD card 82 | # NOTE: All data on the SD card will be lost. 83 | diskutil eraseDisk fat32 %noformat% disk5 84 | 85 | # Unmount the SD card 86 | diskutil unmountDisk /dev/disk5 87 | 88 | # Write image to SD card 89 | # WARNING: If you misuse the dd command you can end up destroying your system and lose data 90 | # Double-check this command twice and make sure that of=/dev/rdisk5 corresponds to your SD card. 91 | # dd will not warn you before overwriting your boot partition. It will do exactly what you tell it to. Silently. 92 | # 93 | # if = input file (where to read from) 94 | # of = output file (where to write to) 95 | # bs = block size in bytes 96 | # 97 | # Here we read from the image file and write directly to the (unbuffered) block device /dev/rdisk5 98 | sudo dd if=hypriot-rpi-20160306-192317.img of=/dev/rdisk5 bs=524288 99 | 100 | # Insert the SD card into your Raspberry Pi and plug the Pi with an Ethernet cable to your router. It needs a DHCP server to get an IP address. 101 | # When the Pi has booted, find its IP from the router's list of connected hosts. 102 | 103 | The default SSH username is `root` with password `hypriot`. 104 | 105 | ## Pi setup 106 | 107 | *Time required: 4 min* 108 | 109 | The initial setup assumes that you already have an SSH keypair at `~/.ssh/id_rsa` and `~/.ssh/id_rsa.pub`. 110 | 111 | # Add the Raspberry Pi IP to the file `hosts` 112 | # Replace 192.168.0.123 with the IP of your Raspberry Pi. 113 | echo "[pi] 114 | 192.168.0.123" > hosts 115 | 116 | # Run the playbook 117 | # The password is `hypriot` 118 | ansible-playbook initial_setup.yml --user root --ask-pass 119 | 120 | 121 | ## Build Dockerimages 122 | 123 | *Time required: 53 min* 124 | 125 | # Run playbook 126 | # Registry role takes 31 min 127 | # Apache role takes 22 min 128 | 129 | ansible-playbook build.yml 130 | 131 | ## Configure 132 | 133 | *Time required: 10 min* 134 | 135 | This is a variation on the script from the [official site](https://docs.docker.com/registry/apache/). You will need Docker locally for one of the tasks. 136 | 137 | # Ensure that you have put your certificate and key files 138 | # in ~/.ssl/registry/ 139 | # Update the variables ssl_certificate and ssl_key in configure.yml 140 | # if your keys are elsewhere and/or have other names. 141 | 142 | # Run the playbook (replace domain name with yours) 143 | ansible-playbook configure.yml -e "registry_fqdn=yourregistrydomain.com" 144 | 145 | # Ensure your DNS record is updated with the IP of Raspberry Pi. 146 | # Then check (you may need to flush your DNS cache first) 147 | curl https://myregistrydomain.com 148 | 149 | ## Login 150 | 151 | From your local machine, you can now start interacting with the registry. 152 | 153 | # Log in as admin 154 | docker login myregistrydomain.com 155 | Username: admin 156 | Password: 157 | Login Succeeded 158 | 159 | # Push an image 160 | docker pull busybox 161 | docker tag busybox myregistrydomain.com/library/busybox 162 | docker push myregistrydomain.com/library/busybox 163 | The push refers to a repository [myregistrydomain.com/library/busybox] 164 | 5f70bf18a086: Pushed 165 | 1834950e52ce: Pushed 166 | latest: digest: sha256:6757d4b17cd75742fc3b1fc1a8d02b45b637f2ac913ee9669f5c2aed0c9b26ba size: 711 167 | 168 | # Log in as the user 169 | docker login myregistrydomain.com 170 | Username: user 171 | Password: 172 | Email: 173 | Login Succeeded 174 | 175 | # Pull image 176 | docker pull myregistrydomain.com/library/busybox 177 | Using default tag: latest 178 | latest: Pulling from library/busybox 179 | 180 | 385e281300cc: Already exists 181 | a3ed95caeb02: Already exists 182 | Digest: sha256:4a731fb46adc5cefe3ae374a8b6020fc1b6ad667a279647766e9a3cd89f6fa92 183 | Status: Image is up to date for myregistrydomain.com/library/busybox:latest 184 | 185 | # Try pushing as user (won't work!) 186 | docker push myregistrydomain.com/library/busybox 187 | The push refers to a repository [myregistrydomain.com/library/busybox] 188 | 5f70bf18a086: Layer already exists 189 | 1834950e52ce: Layer already exists 190 | unauthorized: authentication required 191 | 192 | # Limitations 193 | 194 | * Only tested on Raspberry Pi 3. 195 | * Building takes Forever[tm] - plenty of room for slimming down images and shortening build time 196 | -------------------------------------------------------------------------------- /ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory=hosts 3 | host_key_checking=False 4 | -------------------------------------------------------------------------------- /build.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: pi 3 | become: true 4 | 5 | roles: 6 | - registry 7 | - apache 8 | -------------------------------------------------------------------------------- /configure.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: pi 3 | become: true 4 | 5 | vars_prompt: 6 | - name: "admin_password" 7 | prompt: "Please input an admin password (hit enter to leave it unchanged)" 8 | private: yes 9 | - name: "user_password" 10 | prompt: "Please input a user password (hit enter to leave it unchanged)" 11 | private: yes 12 | 13 | vars: 14 | - ssl_certificate: "~/.ssl/registry/fullchain1.pem" 15 | - ssl_key: "~/.ssl/registry/privkey1.pem" 16 | 17 | roles: 18 | - auth 19 | - start 20 | -------------------------------------------------------------------------------- /hosts: -------------------------------------------------------------------------------- 1 | [pi] 2 | 192.168.0.21 3 | -------------------------------------------------------------------------------- /initial_setup.yml: -------------------------------------------------------------------------------- 1 | - hosts: pi 2 | gather_facts: no 3 | 4 | vars: 5 | - username: "{{ whoami.stdout }}" 6 | 7 | roles: 8 | - setup 9 | -------------------------------------------------------------------------------- /roles/apache/files/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM hypriot/rpi-golang:tar-1.5.2 2 | 3 | # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added 4 | #RUN groupadd -r www-data && useradd -r --create-home -g www-data www-data 5 | 6 | ENV HTTPD_PREFIX /usr/local/apache2 7 | ENV PATH $PATH:$HTTPD_PREFIX/bin 8 | RUN mkdir -p "$HTTPD_PREFIX" \ 9 | && chown www-data:www-data "$HTTPD_PREFIX" 10 | WORKDIR $HTTPD_PREFIX 11 | 12 | # install httpd runtime dependencies 13 | # https://httpd.apache.org/docs/2.4/install.html#requirements 14 | RUN apt-get update \ 15 | && apt-get install -y --no-install-recommends \ 16 | libapr1 \ 17 | libaprutil1 \ 18 | libapr1-dev \ 19 | libaprutil1-dev \ 20 | libpcre++0 \ 21 | libssl1.0.0 \ 22 | && rm -r /var/lib/apt/lists/* 23 | 24 | ENV HTTPD_VERSION 2.4.18 25 | ENV HTTPD_BZ2_URL https://www.apache.org/dist/httpd/httpd-$HTTPD_VERSION.tar.bz2 26 | 27 | RUN buildDeps=' \ 28 | ca-certificates \ 29 | curl \ 30 | bzip2 \ 31 | gcc \ 32 | libpcre++-dev \ 33 | libssl-dev \ 34 | make \ 35 | ' \ 36 | set -x \ 37 | && apt-get update \ 38 | && apt-get install -y --no-install-recommends $buildDeps \ 39 | && rm -r /var/lib/apt/lists/* \ 40 | && curl -fSL "$HTTPD_BZ2_URL" -o httpd.tar.bz2 \ 41 | && curl -fSL "$HTTPD_BZ2_URL.asc" -o httpd.tar.bz2.asc \ 42 | # see https://httpd.apache.org/download.cgi#verify 43 | && export GNUPGHOME="$(mktemp -d)" \ 44 | && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys A93D62ECC3C8EA12DB220EC934EA76E6791485A8 \ 45 | && gpg --batch --verify httpd.tar.bz2.asc httpd.tar.bz2 \ 46 | && rm -r "$GNUPGHOME" httpd.tar.bz2.asc \ 47 | && mkdir -p src/httpd \ 48 | && tar -xvf httpd.tar.bz2 -C src/httpd --strip-components=1 \ 49 | && rm httpd.tar.bz2 \ 50 | && cd src/httpd \ 51 | && ./configure --enable-so --enable-ssl --prefix=$HTTPD_PREFIX --enable-mods-shared=most \ 52 | && make -j"$(nproc)" \ 53 | && make install \ 54 | && cd ../../ \ 55 | && rm -r src/httpd \ 56 | && sed -ri ' \ 57 | s!^(\s*CustomLog)\s+\S+!\1 /proc/self/fd/1!g; \ 58 | s!^(\s*ErrorLog)\s+\S+!\1 /proc/self/fd/2!g; \ 59 | ' /usr/local/apache2/conf/httpd.conf \ 60 | && apt-get purge -y --auto-remove $buildDeps 61 | 62 | COPY httpd-foreground /usr/local/bin/ 63 | 64 | EXPOSE 80 65 | CMD ["httpd-foreground"] 66 | -------------------------------------------------------------------------------- /roles/apache/files/httpd-foreground: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Apache gets grumpy about PID files pre-existing 5 | rm -f /usr/local/apache2/logs/httpd.pid 6 | 7 | exec httpd -DFOREGROUND 8 | -------------------------------------------------------------------------------- /roles/apache/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ensure rpi-httpd directory is created 3 | file: 4 | path: "/root/rpi-httpd" 5 | state: "directory" 6 | 7 | - name: ensure files are uploaded 8 | copy: 9 | src: "{{ item }}" 10 | dest: "/root/rpi-httpd" 11 | with_fileglob: "*" #all files in this role's files directory 12 | 13 | - name: ensure httpd-foreground is runnable 14 | file: 15 | path: "/root/rpi-httpd/httpd-foreground" 16 | mode: "755" 17 | 18 | - name: check if dockerimage exists 19 | shell: docker images | grep rpi-httpd | awk '{ print $2 }' 20 | register: docker_image_tag 21 | changed_when: false 22 | 23 | - name: build dockerimage 24 | command: "docker build --tag rpi-httpd:2.4 ." 25 | args: 26 | chdir: "/root/rpi-httpd" 27 | when: docker_image_tag.stdout != "2.4" 28 | -------------------------------------------------------------------------------- /roles/auth/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: ensure auth and data directories are created 3 | file: 4 | path: "/root/{{ item }}" 5 | state: "directory" 6 | with_items: 7 | - "data" 8 | - "auth" 9 | 10 | - name: ensure httpd conf is uploaded 11 | template: 12 | src: "httpd.conf.j2" 13 | dest: "/root/auth/httpd.conf" 14 | 15 | - name: get htpasswd file contents 16 | command: "cat /root/auth/httpd.htpasswd" 17 | ignore_errors: yes 18 | changed_when: false 19 | register: htpasswd 20 | 21 | - name: generate admin password hash 22 | delegate_to: localhost 23 | connection: local 24 | become: false 25 | command: "docker run --entrypoint htpasswd httpd:2.4 -bn admin {{ admin_password }}" 26 | when: not htpasswd.stdout | search('admin') or (admin_password is defined and admin_password != "") 27 | register: generated_password 28 | 29 | - name: add admin to htpasswd 30 | lineinfile: 31 | regexp: "^admin" 32 | line: "{{ generated_password.stdout }}" 33 | dest: "/root/auth/httpd.htpasswd" 34 | create: yes 35 | when: generated_password | changed 36 | 37 | - name: generate user password hash 38 | delegate_to: localhost 39 | connection: local 40 | become: false 41 | command: "docker run --entrypoint htpasswd httpd:2.4 -bn user {{ user_password }}" 42 | when: not htpasswd.stdout | search('user') or (user_password is defined and user_password != "") 43 | register: generated_password_user 44 | 45 | - name: add user to htpasswd 46 | lineinfile: 47 | regexp: "^user" 48 | line: "{{ generated_password_user.stdout }}" 49 | dest: "/root/auth/httpd.htpasswd" 50 | create: yes 51 | when: generated_password_user | changed 52 | 53 | - name: ensure admin is added to pusher group 54 | lineinfile: 55 | regexp: "^pusher" 56 | line: "pusher: admin" 57 | dest: "/root/auth/httpd.groups" 58 | create: yes 59 | 60 | - name: ensure ssl certificate is uploaded 61 | copy: 62 | src: "{{ ssl_certificate }}" 63 | dest: "/root/auth/domain.crt" 64 | 65 | - name: ensure ssl key is uploaded 66 | copy: 67 | src: "{{ ssl_key }}" 68 | dest: "/root/auth/domain.key" 69 | -------------------------------------------------------------------------------- /roles/auth/templates/httpd.conf.j2: -------------------------------------------------------------------------------- 1 | LoadModule headers_module modules/mod_headers.so 2 | 3 | LoadModule authn_file_module modules/mod_authn_file.so 4 | LoadModule authn_core_module modules/mod_authn_core.so 5 | LoadModule authz_groupfile_module modules/mod_authz_groupfile.so 6 | LoadModule authz_user_module modules/mod_authz_user.so 7 | LoadModule authz_core_module modules/mod_authz_core.so 8 | LoadModule auth_basic_module modules/mod_auth_basic.so 9 | LoadModule access_compat_module modules/mod_access_compat.so 10 | 11 | LoadModule log_config_module modules/mod_log_config.so 12 | 13 | LoadModule ssl_module modules/mod_ssl.so 14 | 15 | LoadModule proxy_module modules/mod_proxy.so 16 | LoadModule proxy_http_module modules/mod_proxy_http.so 17 | 18 | LoadModule unixd_module modules/mod_unixd.so 19 | 20 | 21 | SSLRandomSeed startup builtin 22 | SSLRandomSeed connect builtin 23 | 24 | 25 | 26 | User daemon 27 | Group daemon 28 | 29 | 30 | ServerAdmin you@example.com 31 | 32 | ErrorLog /proc/self/fd/2 33 | 34 | LogLevel warn 35 | 36 | 37 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined 38 | LogFormat "%h %l %u %t \"%r\" %>s %b" common 39 | 40 | 41 | LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio 42 | 43 | 44 | CustomLog /proc/self/fd/1 common 45 | 46 | 47 | ServerRoot "/usr/local/apache2" 48 | 49 | Listen 5043 50 | 51 | 52 | AllowOverride none 53 | Require all denied 54 | 55 | 56 | 57 | 58 | ServerName {{ registry_fqdn }} 59 | 60 | SSLEngine on 61 | SSLCertificateFile /usr/local/apache2/conf/domain.crt 62 | SSLCertificateKeyFile /usr/local/apache2/conf/domain.key 63 | 64 | ## SSL settings recommandation from: https://raymii.org/s/tutorials/Strong_SSL_Security_On_Apache2.html 65 | # Anti CRIME 66 | SSLCompression off 67 | 68 | # POODLE and other stuff 69 | SSLProtocol all -SSLv2 -SSLv3 -TLSv1 70 | 71 | # Secure cypher suites 72 | SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH 73 | SSLHonorCipherOrder on 74 | 75 | Header always set "Docker-Distribution-Api-Version" "registry/2.0" 76 | Header onsuccess set "Docker-Distribution-Api-Version" "registry/2.0" 77 | RequestHeader set X-Forwarded-Proto "https" 78 | 79 | ProxyRequests off 80 | ProxyPreserveHost on 81 | 82 | # no proxy for /error/ (Apache HTTPd errors messages) 83 | ProxyPass /error/ ! 84 | 85 | ProxyPass /v2 http://registry:5000/v2 86 | ProxyPassReverse /v2 http://registry:5000/v2 87 | 88 | 89 | Order deny,allow 90 | Allow from all 91 | AuthName "Registry Authentication" 92 | AuthType basic 93 | AuthUserFile "/usr/local/apache2/conf/httpd.htpasswd" 94 | AuthGroupFile "/usr/local/apache2/conf/httpd.groups" 95 | 96 | # Read access to authentified users 97 | 98 | Require valid-user 99 | 100 | 101 | # Write access to docker-deployer only 102 | 103 | Require group pusher 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /roles/registry/files/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM hypriot/rpi-golang:tar-1.5.2 2 | 3 | RUN apt-get update && \ 4 | apt-get install -y wget apache2-utils && \ 5 | rm -rf /var/lib/apt/lists/* 6 | 7 | WORKDIR /root 8 | 9 | RUN wget https://github.com/hypriot/golang-armbuilds/releases/download/v1.5.2/go1.5.2.linux-armv7.tar.gz && tar -xvzf go1.5.2.linux-armv7.tar.gz -C /usr/local 10 | ENV PATH /usr/local/go/bin:$PATH 11 | 12 | ENV DISTRIBUTION_DIR /go/src/github.com/docker/distribution 13 | ENV GOPATH $DISTRIBUTION_DIR/Godeps/_workspace:/go 14 | ENV GOROOT /usr/local/go 15 | ENV DOCKER_BUILDTAGS include_oss include_gcs 16 | 17 | WORKDIR $DISTRIBUTION_DIR 18 | COPY . $DISTRIBUTION_DIR 19 | COPY cmd/registry/config-dev.yml /etc/docker/registry/config.yml 20 | RUN make PREFIX=/go clean binaries 21 | 22 | VOLUME ["/var/lib/registry"] 23 | EXPOSE 5000 24 | ENTRYPOINT ["registry"] 25 | CMD ["serve", "/etc/docker/registry/config.yml"] 26 | -------------------------------------------------------------------------------- /roles/registry/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: ensure distribution repo is cloned 2 | git: 3 | repo: "https://github.com/docker/distribution.git" 4 | dest: "/root/distribution" 5 | update: "no" 6 | 7 | - name: ensure modified dockerfile is uploaded 8 | copy: 9 | src: "Dockerfile" 10 | dest: "/root/distribution/" 11 | 12 | - name: check if dockerimage exists 13 | command: docker images 14 | register: docker_images 15 | changed_when: false 16 | 17 | - name: build dockerimage 18 | command: "docker build --tag rpi-registry ." 19 | args: 20 | chdir: "/root/distribution/" 21 | when: not docker_images.stdout | search('rpi-registry') 22 | -------------------------------------------------------------------------------- /roles/setup/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: restart ssh 2 | service: 3 | name: ssh 4 | state: restarted 5 | -------------------------------------------------------------------------------- /roles/setup/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: check if python is installed 3 | raw: python --version 4 | ignore_errors: yes 5 | register: python_check 6 | 7 | - name: ensure python is installed 8 | raw: apt-get update && apt-get install -y python-simplejson 9 | when: python_check | failed 10 | 11 | - name: get local username 12 | command: whoami 13 | delegate_to: localhost 14 | connection: local 15 | become: false 16 | register: whoami 17 | changed_when: false 18 | 19 | - name: ensure user is created 20 | user: 21 | name: "{{ username }}" 22 | home: "/home/{{ username }}" 23 | 24 | - name: ensure user is added to sudoers 25 | copy: 26 | dest: "/etc/sudoers.d/user-{{ username }}" 27 | content: "{{ username }} ALL=NOPASSWD: ALL" 28 | 29 | - name: ensure ssh directory exists 30 | file: 31 | path: "/home/{{ username }}/.ssh" 32 | owner: "{{ username }}" 33 | group: "{{ username }}" 34 | state: "directory" 35 | 36 | - name: ensure ssh public key is uploaded for user 37 | authorized_key: 38 | user: "{{ username }}" 39 | key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" 40 | path: "/home/{{ username }}/.ssh/authorized_keys" 41 | 42 | - name: ensure root and password ssh are disabled 43 | lineinfile: 44 | line: "{{ item }} no" 45 | regexp: "^{{ item }}" 46 | dest: "/etc/ssh/sshd_config" 47 | with_items: 48 | - "PasswordAuthentication" 49 | - "PermitRootLogin" 50 | notify: restart ssh 51 | 52 | - name: ensure pi user is removed 53 | user: 54 | name: "pi" 55 | state: "absent" 56 | -------------------------------------------------------------------------------- /roles/setup/templates/zshrc.j2: -------------------------------------------------------------------------------- 1 | # Lines configured by zsh-newuser-install 2 | HISTFILE=~/.histfile 3 | HISTSIZE=10000000 4 | SAVEHIST=10000000 5 | setopt appendhistory autocd beep extendedglob nomatch notify 6 | bindkey -v 7 | # End of lines configured by zsh-newuser-install 8 | # The following lines were added by compinstall 9 | zstyle :compinstall filename '/home/{{ username }}/.zshrc' 10 | 11 | autoload -Uz compinit 12 | compinit 13 | # End of lines added by compinstall 14 | -------------------------------------------------------------------------------- /roles/start/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: check if registry is running 2 | command: "docker ps" 3 | register: running_status 4 | changed_when: false 5 | 6 | - name: check all containers 7 | command: "docker ps -a" 8 | register: all_status 9 | changed_when: false 10 | 11 | - name: remove old registry container if stopped 12 | command: "docker rm registry" 13 | when: not running_status.stdout | search('rpi-registry') and all_status.stdout | search('rpi-registry') 14 | 15 | - name: start registry 16 | command: "docker run -d -p 127.0.0.1:5000:5000 -v /root/data:/var/lib/registry --name registry rpi-registry" 17 | when: not running_status.stdout | search('rpi-registry') 18 | 19 | - name: check that registry is running (if this fails registry is not working properly) 20 | command: "curl localhost:5000/v2/" 21 | register: curl_check 22 | failed_when: curl_check.stdout != "{}" 23 | changed_when: false 24 | 25 | - name: remove old apache container if stopped 26 | command: "docker rm apache" 27 | when: not running_status.stdout | search('rpi-httpd') and all_status.stdout | search('rpi-httpd') 28 | 29 | - name: start apache 30 | command: "docker run -d -p 443:5043 -v /root/auth:/usr/local/apache2/conf --hostname {{ registry_fqdn }} --link registry:registry --name apache rpi-httpd:2.4" 31 | when: not running_status.stdout | search('rpi-httpd') 32 | --------------------------------------------------------------------------------