diff --git a/README.md b/README.md new file mode 100644 index 0000000..c9d5d0a --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Description + +This is a deployment [Conan](https://conan.io/) server, which is a decentralized and multi-platform +package manager. + +# Details + +Conan runs as a container on the host and exposes port `9300` which is the proxied via Nginx to regular HTTPS via `443`. + +The backups are generated __TODO__ and uploaded to a Digital Ocean space. For configuration details see [`defaults/main.yml`](./defaults/main.yml). + +# Usage + +Simply point Conan at the HTTPS endpoint: +```bash +conan remote add status-repo https://conan.status.im/ +``` +And add your user for repo access: +```bash +% conan user admin --remote=status-repo [11/01/18 13:55:04] +Please enter a password for "admin" account: +Changed user of remote 'status-repo' from 'None' (anonymous) to 'admin' +``` + +# Docker Image + +The image used is custom because we wanted to use GUnicorn for hosting the server +It comes from the [`infra-utils`](https://github.com/status-im/infra-utils/tree/master/conan) repo. + +# Documentation + +* https://hub.docker.com/r/cguenther/conan-server/ +* https://docs.conan.io/en/latest/uploading_packages/running_your_server.html +* https://docs.conan.io/en/latest/uploading_packages/uploading_to_remotes.html + +# Known Issues + +* Backups of repo diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..4a338a5 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,23 @@ +--- +# Ghost settings +conan_domain: 'conan.status.im' +conan_cont_image: 'statusteam/conan:latest' +conan_cont_name: 'conan-server' +conan_cont_port: 9300 +conan_cont_workers: 4 +conan_cont_timeout: 300 +conan_cont_vol: '/docker/{{ conan_cont_name }}' +conan_max_upload: 800m +# container specific settings +conan_cont_home: '/root/.conan_server' + +conan_users: + - name: admin + pass: '{{lookup("passwordstore", "services/conan/admin-pass")}}' + write: true + - name: status + pass: '{{lookup("passwordstore", "services/conan/status-pass")}}' + write: true + - name: test + pass: test + write: false diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..bb5d7e5 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Save iptables rules + shell: iptables-save > /etc/iptables/rules.v4 + +- name: reload nginx + service: name=nginx state=reloaded diff --git a/tasks/config.yml b/tasks/config.yml new file mode 100644 index 0000000..b70e914 --- /dev/null +++ b/tasks/config.yml @@ -0,0 +1,17 @@ +--- +- name: 'Create directories for {{ conan_cont_name }}' + file: + path: '{{ conan_cont_vol }}/{{ item }}' + state: directory + owner: 'dockremap' + recurse: true + with_items: + - 'conf' + - 'data' + +- name: 'Generate the {{ conan_cont_name }} config' + template: + src: server.conf.j2 + dest: '{{ conan_cont_vol }}/conf/server.conf' + owner: 'dockremap' + register: config diff --git a/tasks/consul.yml b/tasks/consul.yml new file mode 100644 index 0000000..c83636f --- /dev/null +++ b/tasks/consul.yml @@ -0,0 +1,15 @@ +--- +- name: Consul service definition + include_role: name=consul-service + vars: + consul_config_name: '{{ conan_cont_name }}' + consul_services: + - id: '{{ conan_cont_name }}' + name: '{{ conan_cont_name }}' + port: '{{ conan_cont_port }}' + address: 'localhost' + tags: ['{{ env }}.{{ stage }}', 'conan', 'repo'] + checks: + - id: '{{ conan_cont_name }}-health' + type: http + http: 'http://localhost:{{ conan_cont_port }}/v2/ping' diff --git a/tasks/container.yml b/tasks/container.yml new file mode 100644 index 0000000..11a14d1 --- /dev/null +++ b/tasks/container.yml @@ -0,0 +1,19 @@ +--- +- name: 'Start container: {{ conan_cont_name }}' + docker_container: + name: '{{ conan_cont_name }}' + image: '{{ conan_cont_image }}' + pull: true + restart_policy: always + state: '{{ cont_state }}' + recreate: '{{ cont_recreate }}' + restart: '{{ config.changed | default(cont_restart) }}' + ports: + - '{{ conan_cont_port }}:{{ conan_cont_port }}' + env: + CONAN_PORT: '{{ conan_cont_port | string }}' + CONAN_WORKERS: '{{ conan_cont_workers | string }}' + CONAN_TIMEOUT: '{{ conan_cont_timeout | string }}' + volumes: + - '{{ conan_cont_vol }}/data:{{ conan_cont_home }}/data' + - '{{ conan_cont_vol }}/conf/server.conf:{{ conan_cont_home }}/server.conf' diff --git a/tasks/firewall.yml b/tasks/firewall.yml new file mode 100644 index 0000000..4647358 --- /dev/null +++ b/tasks/firewall.yml @@ -0,0 +1,14 @@ +--- +- name: 'Enable {{ conan_cont_name }}' + iptables: + comment: '{{ conan_cont_name }}' + chain: INPUT + jump: ACCEPT + source: '0.0.0.0/0' + protocol: 'tcp' + destination_port: '{{ item }}' + with_items: + - 80 + - 443 + notify: + - Save iptables rules diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..2829619 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,6 @@ +--- +- include_tasks: config.yml +- include_tasks: container.yml +- include_tasks: consul.yml +- include_tasks: proxy.yml +- include_tasks: firewall.yml diff --git a/tasks/proxy.yml b/tasks/proxy.yml new file mode 100644 index 0000000..5d04f71 --- /dev/null +++ b/tasks/proxy.yml @@ -0,0 +1,13 @@ +--- +- name: 'Template Ghost proxy config: {{ conan_cont_name }}' + template: + src: conan-proxy.conf.j2 + dest: '/etc/nginx/sites-available/{{ conan_cont_name }}.conf' + notify: reload nginx + +- name: 'Symlink Ghost proxy config: {{ conan_cont_name }}' + file: + src: '/etc/nginx/sites-available/{{ conan_cont_name }}.conf' + dest: '/etc/nginx/sites-enabled/{{ conan_cont_name }}.conf' + state: link + notify: reload nginx diff --git a/templates/conan-proxy.conf.j2 b/templates/conan-proxy.conf.j2 new file mode 100644 index 0000000..56b507b --- /dev/null +++ b/templates/conan-proxy.conf.j2 @@ -0,0 +1,24 @@ +server { + listen 80; + server_name {{ conan_domain }}; + return 302 https://$host$request_uri; +} + +server { + listen 443 ssl; + + server_name {{ conan_domain }}; + + ssl_certificate /certs/origin.crt; + ssl_certificate_key /certs/origin.key; + + client_max_body_size {{ conan_max_upload }}; + + location / { + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_pass http://127.0.0.1:{{ conan_cont_port }}/; + } +} diff --git a/templates/server.conf.j2 b/templates/server.conf.j2 new file mode 100644 index 0000000..90bb612 --- /dev/null +++ b/templates/server.conf.j2 @@ -0,0 +1,30 @@ +[server] +updown_secret: {{lookup("passwordstore", "services/conan/updown-secret")}} +jwt_secret: {{lookup("passwordstore", "services/conan/jwt-secret")}} +jwt_expire_minutes: 120 + +authorize_timeout: 1800 + +# This affects actual listen port +port: {{ conan_cont_port }} +# These 3 affect how server advertises itself publicly +ssl_enabled: True +public_port: 443 +host_name: {{ conan_domain }} + +store_adapter: disk +# Just for disk storage adapter +disk_storage_path: {{ conan_cont_home }}/data +disk_authorize_timeout: 1800 + +[read_permissions] +# By default all users can read all blocks +*/*@*/*: * + +[write_permissions] +*/*@*/*: {{ conan_users | selectattr("write", "equalto", True) | map(attribute="name") | join(",") }} + +[users] +{% for user in conan_users %} +{{ user.name }}: {{ user.pass }} +{% endfor %}