From 9ec34e76615556096f75291c57872948e76f7aef Mon Sep 17 00:00:00 2001 From: Jan Beilicke Date: Sun, 12 Apr 2020 00:17:39 +0200 Subject: [PATCH] Initial commit --- .travis.yml | 29 +++ LICENSE | 19 ++ README.md | 44 ++++ defaults/main.yml | 6 + handlers/main.yml | 2 + meta/main.yml | 53 ++++ tasks/main.yml | 79 ++++++ templates/config.js.j2 | 314 +++++++++++++++++++++++ templates/docker-compose.cryptpad.yml.j2 | 48 ++++ tests/inventory | 2 + tests/test.yml | 5 + vars/main.yml | 2 + 12 files changed, 603 insertions(+) create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 defaults/main.yml create mode 100644 handlers/main.yml create mode 100644 meta/main.yml create mode 100644 tasks/main.yml create mode 100644 templates/config.js.j2 create mode 100644 templates/docker-compose.cryptpad.yml.j2 create mode 100644 tests/inventory create mode 100644 tests/test.yml create mode 100644 vars/main.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..36bbf62 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,29 @@ +--- +language: python +python: "2.7" + +# Use the new container infrastructure +sudo: false + +# Install ansible +addons: + apt: + packages: + - python-pip + +install: + # Install ansible + - pip install ansible + + # Check ansible version + - ansible --version + + # Create ansible.cfg with correct roles_path + - printf '[defaults]\nroles_path=../' >ansible.cfg + +script: + # Basic role syntax check + - ansible-playbook tests/test.yml -i tests/inventory --syntax-check + +notifications: + webhooks: https://galaxy.ansible.com/api/v1/notifications/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..86aa256 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +MIT License Copyright (c) 2020 Jan Beilicke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..fd23f2a --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +Cryptpad (Docker-Compose) +========================= + +A single-instance [Cryptpad](https://cryptpad.fr/) server that can be run behind [Traefik](https://traefik.io). + +Requirements +------------ + +- Ansible (implemented and tested with v2.9) +- Ubuntu or Debian server +- [Docker Engine](https://docs.docker.com/install/) + [Docker Compose](https://docs.docker.com/compose/install/) +- Optional: Traefik + +Role Variables +-------------- + +| Variable | Description | Default | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | +| docker_user | The user who is going to manage/run the Docker Compose services | deploy | +| cryptpad_virtual_host | The virtual host that is e.g. used by Traefik, usually part of the public url | localhost | +| cryptpad_safe_virtual_host | See above, and: this additonal domain is used together with `cryptpad_virtual_host` for additional security and must not be the same! More docs are in the `config.js` template | | +| cryptpad_http_unsafe_origin_url | The URL of the public entrypoint URL, e.g. `https://pad.example.tld` | https:// + $cryptpad_virtual_host | +| cryptpad_http_safe_origin_url | The URL of the safe public URL, e.g. `https://pad-sandbox.example.tld` | | +| cryptpad_admin_email | An email address that will be published on the `/contact.html` page | | +| cryptpad_block_daily_check | If enabled, the instance will send some basic information to the developers like the Cryptpad version together with the admin email, which is only used in case there is a serious problem with that version | false | + + +Dependencies +------------ + + + +Example Playbook +---------------- + +License +------- + +MIT + +Author Information +------------------ + +This role was created in 2020 by [Jan Beilicke](https://jotbe.io). diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..9050ece --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,6 @@ +--- +# defaults file for jotbe.cryptpad-docker +cryptpad_http_address: 127.0.0.1 +cryptpad_http_unsafe_origin_url: https://{{ cryptpad_virtual_host }} +cryptpad_http_safe_origin_url: https://{{ cryptpad_safe_virtual_host }} +cryptpad_block_daily_check: no \ No newline at end of file diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..8f8f8ab --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for jotbe.cryptpad-docker \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..227ad9c --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,53 @@ +galaxy_info: + author: your name + description: your role description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Choose a valid license ID from https://spdx.org - some suggested licenses: + # - BSD-3-Clause (default) + # - MIT + # - GPL-2.0-or-later + # - GPL-3.0-only + # - Apache-2.0 + # - CC-BY-4.0 + license: license (GPL-2.0-or-later, MIT, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. + \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..768f1d3 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,79 @@ +--- +# tasks file for jotbe.cryptpad-docker +- name: Ensure Docker Compose project directory exists + file: + path: /home/{{ docker_user }}/cryptpad + state: directory + owner: '{{ docker_user }}' + group: '{{ docker_user }}' + +- name: Provide docker-compose.yml + template: + src: templates/docker-compose.cryptpad.yml.j2 + dest: /home/{{ docker_user }}/cryptpad/docker-compose.yml + owner: "{{ docker_user }}" + group: "{{ docker_user }}" + mode: '0644' + +- name: Output docker-compose.yml + shell: cat /home/{{ docker_user }}/cryptpad/docker-compose.yml + register: output + +- debug: + var: output + +- name: Provide env vars + copy: + dest: /home/{{ docker_user }}/cryptpad/.env + owner: "{{ docker_user }}" + group: "{{ docker_user }}" + mode: '0640' + content: | + VERSION=version-3.15.0 + USE_SSL=false + STORAGE='./storage/file' + LOG_TO_STDOUT=true + +- name: Ensure cryptpad config directory exists + file: + path: /home/{{ docker_user }}/cryptpad/data/config + state: directory + owner: '{{ docker_user }}' + group: '{{ docker_user }}' + +- name: Provide cryptpad config + template: + src: templates/config.js.j2 + dest: /home/{{ docker_user }}/cryptpad/data/config/config.js + owner: "{{ docker_user }}" + group: "{{ docker_user }}" + mode: '0644' + +- name: "docker-compose: Teardown existing cryptpad service" + docker_compose: + project_src: "/home/{{ docker_user }}/cryptpad/" + state: absent + tags: ['never', 'teardown'] + +- name: "docker-compose: Start cryptpad service" + docker_compose: + project_src: "/home/{{ docker_user }}/cryptpad/" + pull: yes + register: output + tags: service_start + +- debug: + var: output + +# - assert: +# that: +# - "output.ansible_facts['cryptpad-app']['cryptpad-app'].state.running" + +- name: "Test whether cryptpad is healthy from the outside" + become: false + uri: + url: "{{ cryptpad_http_unsafe_origin_url }}" + timeout: 300 + validate_certs: no + delegate_to: localhost + tags: health diff --git a/templates/config.js.j2 b/templates/config.js.j2 new file mode 100644 index 0000000..3c07352 --- /dev/null +++ b/templates/config.js.j2 @@ -0,0 +1,314 @@ +/* globals module */ + +/* DISCLAIMER: + + There are two recommended methods of running a CryptPad instance: + + 1. Using a standalone nodejs server without HTTPS (suitable for local development) + 2. Using NGINX to serve static assets and to handle HTTPS for API server's websocket traffic + + We do not officially recommend or support Apache, Docker, Kubernetes, Traefik, or any other configuration. + Support requests for such setups should be directed to their authors. + + If you're having difficulty difficulty configuring your instance + we suggest that you join the project's IRC/Matrix channel. + + If you don't have any difficulty configuring your instance and you'd like to + support us for the work that went into making it pain-free we are quite happy + to accept donations via our opencollective page: https://opencollective.com/cryptpad + +*/ +module.exports = { +/* CryptPad is designed to serve its content over two domains. + * Account passwords and cryptographic content is handled on the 'main' domain, + * while the user interface is loaded on a 'sandbox' domain + * which can only access information which the main domain willingly shares. + * + * In the event of an XSS vulnerability in the UI (that's bad) + * this system prevents attackers from gaining access to your account (that's good). + * + * Most problems with new instances are related to this system blocking access + * because of incorrectly configured sandboxes. If you only see a white screen + * when you try to load CryptPad, this is probably the cause. + * + * PLEASE READ THE FOLLOWING COMMENTS CAREFULLY. + * + */ + +/* httpUnsafeOrigin is the URL that clients will enter to load your instance. + * Any other URL that somehow points to your instance is supposed to be blocked. + * The default provided below assumes you are loading CryptPad from a server + * which is running on the same machine, using port 3000. + * + * In a production instance this should be available ONLY over HTTPS + * using the default port for HTTPS (443) ie. https://cryptpad.fr + * In such a case this should be handled by NGINX, as documented in + * cryptpad/docs/example.nginx.conf (see the $main_domain variable) + * + */ + httpUnsafeOrigin: '{{ cryptpad_http_unsafe_origin_url }}', + +/* httpSafeOrigin is the URL that is used for the 'sandbox' described above. + * If you're testing or developing with CryptPad on your local machine then + * it is appropriate to leave this blank. The default behaviour is to serve + * the main domain over port 3000 and to serve the content over port 3001. + * + * This is not appropriate in a production environment where invasive networks + * may filter traffic going over abnormal ports. + * To correctly configure your production instance you must provide a URL + * with a different domain (a subdomain is sufficient). + * It will be used to load the UI in our 'sandbox' system. + * + * This value corresponds to the $sandbox_domain variable + * in the example nginx file. + * + * CUSTOMIZE AND UNCOMMENT THIS FOR PRODUCTION INSTALLATIONS. + */ + httpSafeOrigin: "{{ cryptpad_http_safe_origin_url }}", + +/* httpAddress specifies the address on which the nodejs server + * should be accessible. By default it will listen on 127.0.0.1 + * (IPv4 localhost on most systems). If you want it to listen on + * all addresses, including IPv6, set this to '::'. + * + */ + httpAddress: '0.0.0.0', + +/* httpPort specifies on which port the nodejs server should listen. + * By default it will serve content over port 3000, which is suitable + * for both local development and for use with the provided nginx example, + * which will proxy websocket traffic to your node server. + * + */ + //httpPort: 3000, + +/* httpSafePort allows you to specify an alternative port from which + * the node process should serve sandboxed assets. The default value is + * that of your httpPort + 1. You probably don't need to change this. + * + */ + //httpSafePort: 3001, + + /* ===================== + * Admin + * ===================== */ + + /* + * CryptPad contains an administration panel. Its access is restricted to specific + * users using the following list. + * To give access to the admin panel to a user account, just add their user id, + * which can be found on the settings page for registered users. + * Entries should be strings separated by a comma. + */ +/* + adminKeys: [ + "https://pad.example.tld/user/#/1/cryptpad-user/UGYuGJrZ2r7KGDigOv1nA+qBAFfES4FrHTc4JtKysLM=", + ], +*/ + + /* CryptPad's administration panel includes a "support" tab + * wherein administrators with a secret key can view messages + * sent from users via the encrypted forms on the /support/ page + * + * To enable this functionality: + * run `node ./scripts/generate-admin-keys.js` + * save the public key in your config in the value below + * add the private key via the admin panel + * and back it up in a secure manner + * + */ + // supportMailboxPublicKey: "", + + /* We're very proud that CryptPad is available to the public as free software! + * We do, however, still need to pay our bills as we develop the platform. + * + * By default CryptPad will prompt users to consider donating to + * our OpenCollective campaign. We publish the state of our finances periodically + * so you can decide for yourself whether our expenses are reasonable. + * + * You can disable any solicitations for donations by setting 'removeDonateButton' to true, + * but we'd appreciate it if you didn't! + */ + //removeDonateButton: false, +{% if cryptpad_admin_email is not undefined %} + /* CryptPad will display a point of contact for your instance on its contact page + * (/contact.html) if you provide it below. + */ + adminEmail: '{{ cryptpad_admin_email }}', +{% endif %} + /* + * By default, CryptPad contacts one of our servers once a day. + * This check-in will also send some very basic information about your instance including its + * version and the adminEmail so we can reach you if we are aware of a serious problem. + * We will never sell it or send you marketing mail. + * + * If you want to block this check-in and remain set 'blockDailyCheck' to true. + */ + blockDailyCheck: {% if cryptpad_block_daily_check %}true{% else %}false{% endif %}, + + /* + * By default users get 50MB of storage by registering on an instance. + * You can set this value to whatever you want. + * + * hint: 50MB is 50 * 1024 * 1024 + */ + //defaultStorageLimit: 50 * 1024 * 1024, + + + /* ===================== + * STORAGE + * ===================== */ + + /* Pads that are not 'pinned' by any registered user can be set to expire + * after a configurable number of days of inactivity (default 90 days). + * The value can be changed or set to false to remove expiration. + * Expired pads can then be removed using a cron job calling the + * `evict-inactive.js` script with node + * + * defaults to 90 days if nothing is provided + */ + //inactiveTime: 90, // days + + /* CryptPad archives some data instead of deleting it outright. + * This archived data still takes up space and so you'll probably still want to + * remove these files after a brief period. + * + * cryptpad/scripts/evict-inactive.js is intended to be run daily + * from a crontab or similar scheduling service. + * + * The intent with this feature is to provide a safety net in case of accidental + * deletion. Set this value to the number of days you'd like to retain + * archived data before it's removed permanently. + * + * defaults to 15 days if nothing is provided + */ + //archiveRetentionTime: 15, + + /* Max Upload Size (bytes) + * this sets the maximum size of any one file uploaded to the server. + * anything larger than this size will be rejected + * defaults to 20MB if no value is provided + */ + //maxUploadSize: 20 * 1024 * 1024, + + /* + * CryptPad allows administrators to give custom limits to their friends. + * add an entry for each friend, identified by their user id, + * which can be found on the settings page. Include a 'limit' (number of bytes), + * a 'plan' (string), and a 'note' (string). + * + * hint: 1GB is 1024 * 1024 * 1024 bytes + */ +/* + customLimits: { + "https://my.awesome.website/user/#/1/cryptpad-user1/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=": { + limit: 20 * 1024 * 1024 * 1024, + plan: 'insider', + note: 'storage space donated by my.awesome.website' + }, + "https://my.awesome.website/user/#/1/cryptpad-user2/GdflkgdlkjeworijfkldfsdflkjeEAsdlEnkbx1vVOo=": { + limit: 10 * 1024 * 1024 * 1024, + plan: 'insider', + note: 'storage space donated by my.awesome.website' + } + }, +*/ + + /* Users with premium accounts (those with a plan included in their customLimit) + * can benefit from an increased upload size limit. By default they are restricted to the same + * upload size as any other registered user. + * + */ + //premiumUploadSize: 100 * 1024 * 1024, + + /* ===================== + * DATABASE VOLUMES + * ===================== */ + + /* + * CryptPad stores each document in an individual file on your hard drive. + * Specify a directory where files should be stored. + * It will be created automatically if it does not already exist. + */ + filePath: './datastore/', + + /* CryptPad offers the ability to archive data for a configurable period + * before deleting it, allowing a means of recovering data in the event + * that it was deleted accidentally. + * + * To set the location of this archive directory to a custom value, change + * the path below: + */ + archivePath: './data/archive', + + /* CryptPad allows logged in users to request that particular documents be + * stored by the server indefinitely. This is called 'pinning'. + * Pin requests are stored in a pin-store. The location of this store is + * defined here. + */ + pinPath: './data/pins', + + /* if you would like the list of scheduled tasks to be stored in + a custom location, change the path below: + */ + taskPath: './data/tasks', + + /* if you would like users' authenticated blocks to be stored in + a custom location, change the path below: + */ + blockPath: './block', + + /* CryptPad allows logged in users to upload encrypted files. Files/blobs + * are stored in a 'blob-store'. Set its location here. + */ + blobPath: './blob', + + /* CryptPad stores incomplete blobs in a 'staging' area until they are + * fully uploaded. Set its location here. + */ + blobStagingPath: './data/blobstage', + + /* CryptPad supports logging events directly to the disk in a 'logs' directory + * Set its location here, or set it to false (or nothing) if you'd rather not log + */ + logPath: './data/logs', + + /* ===================== + * Debugging + * ===================== */ + + /* CryptPad can log activity to stdout + * This may be useful for debugging + */ + logToStdout: true, + + /* CryptPad can be configured to log more or less + * the various settings are listed below by order of importance + * + * silly, verbose, debug, feedback, info, warn, error + * + * Choose the least important level of logging you wish to see. + * For example, a 'silly' logLevel will display everything, + * while 'info' will display 'info', 'warn', and 'error' logs + * + * This will affect both logging to the console and the disk. + */ + logLevel: 'info', + + /* clients can use the /settings/ app to opt out of usage feedback + * which informs the server of things like how much each app is being + * used, and whether certain clientside features are supported by + * the client's browser. The intent is to provide feedback to the admin + * such that the service can be improved. Enable this with `true` + * and ignore feedback with `false` or by commenting the attribute + * + * You will need to set your logLevel to include 'feedback'. Set this + * to false if you'd like to exclude feedback from your logs. + */ + logFeedback: false, + + /* CryptPad supports verbose logging + * (false by default) + */ + verbose: false, +}; diff --git a/templates/docker-compose.cryptpad.yml.j2 b/templates/docker-compose.cryptpad.yml.j2 new file mode 100644 index 0000000..deaccb0 --- /dev/null +++ b/templates/docker-compose.cryptpad.yml.j2 @@ -0,0 +1,48 @@ +version: '2' +services: + + cryptpad: + image: "cryptpad/cryptpad:${VERSION}" + hostname: cryptpad + + labels: + - "traefik.enable=true" + - "traefik.port=3000" + - "traefik.docker.network=traefik_public" + - "traefik.http.routers.cryptpad.rule=Host(`{{ cryptpad_virtual_host }}`) || Host(`{{ cryptpad_safe_virtual_host }}`)" + - "traefik.http.routers.cryptpad.entrypoints=websecure" + - "traefik.http.routers.cryptpad.tls=true" + - "traefik.http.routers.cryptpad.tls.certresolver=defaultresolver" + - "traefik.http.middlewares.cryptpad-headers.headers.SSLRedirect=true" + - "traefik.http.middlewares.cryptpad-headers.headers.browserXSSFilter=true" + - "traefik.http.middlewares.cryptpad-headers.headers.contentTypeNosniff=true" + - "traefik.http.middlewares.cryptpad-headers.headers.forceSTSHeader=true" + - "traefik.http.middlewares.cryptpad-headers.headers.STSSeconds=315360000" + - "traefik.http.middlewares.cryptpad-headers.headers.STSIncludeSubdomains=true" + - "traefik.http.middlewares.cryptpad-headers.headers.STSPreload=true" + - "traefik.http.middlewares.cryptpad-headers.headers.featurePolicy=geolocation 'none'; payment 'none'" + - "traefik.http.routers.cryptpad.middlewares=cryptpad-headers" + - "traefik.frontend.passHostHeader=true" + environment: + - USE_SSL=${USE_SSL} + - STORAGE=${STORAGE} + - LOG_TO_STDOUT=${LOG_TO_STDOUT} + networks: + public: + + ports: + - "3000:3000" + - "3001:3001" + + restart: unless-stopped + volumes: + - ./data/files:/cryptpad/datastore:rw + - ./data/customize:/cryptpad/customize:rw + - ./data/blob:/cryptpad/blob:rw + - ./data/block:/cryptpad/block:rw + - ./data/config:/cryptpad/cfg:rw + - ./data/data:/cryptpad/data:rw +networks: + public: + external: + name: traefik_public \ No newline at end of file diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..2d4d97d --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - jotbe.cryptpad-docker \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..3b1f7ff --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for jotbe.cryptpad-docker \ No newline at end of file