diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8000dd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vagrant diff --git a/LICENSE b/LICENSE index 204b93d..d745f27 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -MIT License Copyright (c) +MIT License Copyright (c) 2021 "Stichting Disroot.org" Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Playbooks/cryptpad.yml b/Playbooks/cryptpad.yml new file mode 100644 index 0000000..e953ace --- /dev/null +++ b/Playbooks/cryptpad.yml @@ -0,0 +1,9 @@ +--- + +- hosts: cryptpad + roles: + - nginx + - cryptpad + + vars_files: + - ../defaults/main.yml diff --git a/README.md b/README.md index a48f8b0..5a0ce70 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,19 @@ -# Cryptpad +# Cryptpad - Ansible Role +This role deploys and configures cryptpad. You can deploy test instance using `Vagrantfile` attached to the role. + +To have it work using vagrant: +- `vagrant up` to build up the Virtual Environment. +- and `ansible-playbook -b Playbooks/cryptpad.yml` to deploy Cryptpad on the Virtual Environment. + +You can then access at this address: http://192.168.33.20 + +## Playbook +The playbook includes nginx role and deploys entire stack needed to run Cryptpad. Additional role is also available in the Ansible roles repos in git. + +## TODO + - check if it works! + - configure nginx + - ansible the config file + - obviously better Readme file + - Licencing diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..6ab4866 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,19 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# All Vagrant configuration is done below. The "2" in Vagrant.configure +# configures the configuration version (we support older styles for +# backwards compatibility). Please don't change it unless you know what +# you're doing. +Vagrant.configure("2") do |config| + #config.ssh.insert_key = false + config.vm.define "cryptpad" do |cryptpad| + cryptpad.vm.box = "generic/debian10" + cryptpad.vm.provider :libvirt do |libvirt| + libvirt.memory = 256 + end + cryptpad.vm.network "forwarded_port", guest: 80, host: 8888, host_ip: "192.168.33.20" + cryptpad.vm.network "forwarded_port", guest: 443, host: 4443, host_ip: "192.168.33.20" + cryptpad.vm.network "private_network", ip: "192.168.33.20" + end +end diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..6d1511b --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,63 @@ +--- + +cryptpad_user: 'cryptpad' +cryptpad_group: 'cryptpad' +cryptpad_pkg: + - git + - nodejs +cryptpad_node_version: '12' + +cryptpad_path: '/var/www/cryptpad' +cryptpad_version: "4.0.0" + +cryptpad_httpUnsafeOrigin: "http://localhost:3000" +cryptpad_httpSafeOrigin: '' +cryptpad_httpAddress: "::" +cryptpad_httpPort: "3000" +cryptpad_httpSafePort: "3001" +cryptpad_maxWorkers: "4" +cryptpad_adminKeys: "cryptpad-user1@my.awesome.website/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=" +cryptpad_adminEmail: "i.did.not.read.my.config@cryptpad.fr" +cryptpad_removeDonateButton: "false" +cryptpad_blockDailyCheck: "true" +cryptpad_defaultStorageLimit: "50 * 1024 * 1024" # 50 MB +cryptpad_inactiveTime: "90" # in days +cryptpad_archiveRetentionTime: "15" # in days +cryptpad_accountRetentionTime: "365" # in days +cryptpad_disableIntegratedEviction: "true" +cryptpad_maxUploadSize: "20 * 1024 * 1024" # 20 MB +cryptpad_premiumUploadSize: "100 * 1024 * 1024" # 100 MB +cryptpad_filePath: "./datastore/" +cryptpad_archivePath: "./data/archive" +cryptpad_pinPath: "./data/pins" +cryptpad_taskPath: "./data/tasks" +cryptpad_blockPath: "./block" +cryptpad_blobPath: "./blob" +cryptpad_blobStagingPath: "./data/blobstage" +cryptpad_logPath: "./data/logs" +cryptpad_logToStdout: "false" +cryptpad_logLevel: "info" +cryptpad_logFeedback: "false" +cryptpad_verbose: "false" + +cryptpad_LimitNOFILE: "1000000" + +#nginx +nginx_default_vhost: 'cryptpad' +nginx_default_vhost_ssl: 'cryptpad' +nginx_www_dir: '/var/www/' +nginx_vhosts: + +- name: 'cryptpad' + template: 'cryptpad' + proto: 'http' + listen: '80' + http2: true + root: 'cryptpad' + use_access_log: 'true' + use_error_log: 'true' + nginx_error_log_level: 'warn' + state: 'enable' + letsencrypt: 'false' + ssl_name: 'cryptpad.server.org' + proxy_pass: 'localhost' diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..519ff1a --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,6 @@ +--- + +- name: restart cryptpad + service: + name: cryptpad + state: restarted diff --git a/tasks/config.yml b/tasks/config.yml new file mode 100644 index 0000000..ef5cadb --- /dev/null +++ b/tasks/config.yml @@ -0,0 +1,10 @@ +--- + +- name: "[Config]- Deploy cryptpad configuration" + template: + src: config/config.js.j2 + dest: "{{ cryptpad_path }}/config/config.js" + owner: "{{ cryptpad_user }}" + group: "{{ cryptpad_group }}" + mode: 0755 + notify: restart cryptpad diff --git a/tasks/git.yml b/tasks/git.yml new file mode 100644 index 0000000..4ff947c --- /dev/null +++ b/tasks/git.yml @@ -0,0 +1,15 @@ +--- + +- name: "[Version] - Check what cryptpad version is already installed" + shell: + cmd: awk '/cryptpad/{getline; print $2}' {{ cryptpad_path }}/package-lock.json | awk -F\" '{print $2}' + register: cryptpad_version_installed + +- name: '[GIT] - Clone git repo' + git: + repo: https://github.com/xwiki-labs/cryptpad.git + dest: '{{ cryptpad_path }}' + force: yes + version: "{{ cryptpad_version}}" + become: yes + become_user: "{{ cryptpad_user }}" diff --git a/tasks/install.yml b/tasks/install.yml new file mode 100644 index 0000000..07b81b8 --- /dev/null +++ b/tasks/install.yml @@ -0,0 +1,11 @@ +--- + +- name: "[Install] - Cryptpad dependencies via bower" + bower: + path: "{{ cryptpad_path }}" + +- name: "[Install] - Cryptpad via npm" + command: npm install + args: + chdir: "{{ cryptpad_path }}" + become_user: "{{ cryptpad_user }}" diff --git a/tasks/installdeps.yml b/tasks/installdeps.yml new file mode 100644 index 0000000..e65618a --- /dev/null +++ b/tasks/installdeps.yml @@ -0,0 +1,22 @@ +--- + +- name: "[Dependencies] - Add nodejs apt key" + apt_key: + url: https://deb.nodesource.com/gpgkey/nodesource.gpg.key + state: present + +- name: "[Dependencies] - Add nodejs source" + apt_repository: + repo: "deb https://deb.nodesource.com/node_{{ cryptpad_node_version }}.x {{ ansible_distribution_release }} main" + update_cache: yes + +- name: "[Dependencies] - Install Dependencies" + apt: + name: "{{ cryptpad_pkg }}" + update_cache: yes + state: latest + +- name: "[Dependencies] - Install bower" + npm: + name: bower + global: yes diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..6504bae --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,22 @@ +--- + +- name: Create user + include: user.yml + +- name: Install dependencies + include: installdeps.yml + +- name: Clone git repo + include: git.yml + +- name: Install cryptpad + include: install.yml + +- name: Deploy config + include: config.yml + +- name: Systemd + include: systemd.yml + +- name: Update cryptpad + include: update.yml diff --git a/tasks/systemd.yml b/tasks/systemd.yml new file mode 100644 index 0000000..96fcc7a --- /dev/null +++ b/tasks/systemd.yml @@ -0,0 +1,24 @@ +--- + +- name: "[SYSTEMD] - Deploy Systemd config" + template: + src: etc/systemd/system/cryptpad.service.j2 + dest: /etc/systemd/system/cryptpad.service + owner: root + group: root + mode: 0644 + register: cryptpad + +- name: "[SYSTEMD] - Enable systemd" + service: + name: cryptpad + enabled: yes + state: started + notify: + restart cryptpad + +- name: "[SYSTEMD] - Daemon-reload" + systemd: + daemon_reload: yes + name: cryptpad + when: cryptpad.changed diff --git a/tasks/update.yml b/tasks/update.yml new file mode 100644 index 0000000..38e08a2 --- /dev/null +++ b/tasks/update.yml @@ -0,0 +1,15 @@ +--- + +- name: "[Update] - Stop Cryptpad" + service: + name: cryptpad + state: stopped + when: cryptpad_version not in cryptpad_version_installed.stdout + +- name: "[Update] - bower" + command: bower update + args: + chdir: "{{ cryptpad_path }}" + become_user: "{{ cryptpad_user }}" + when: cryptpad_version not in cryptpad_version_installed.stdout + notify: restart cryptpad diff --git a/tasks/user.yml b/tasks/user.yml new file mode 100644 index 0000000..fbad94f --- /dev/null +++ b/tasks/user.yml @@ -0,0 +1,22 @@ +--- + +- name: "[USER] - Add group" + group: + name: '{{ cryptpad_group }}' + state: present + +- name: "[USER] - Add user cryptpad" + user: + name: '{{ cryptpad_user }}' + shell: /bin/bash + group: '{{ cryptpad_group }}' + #home: '{{ cryptpad_path }}' + state: present + +- name: '[User] - Change ownership to cryptpad user' + file: + path: '{{ cryptpad_path }}' + owner: '{{ cryptpad_user }}' + group: '{{ cryptpad_group }}' + state: directory + recurse: yes diff --git a/templates/config/config.js.j2 b/templates/config/config.js.j2 new file mode 100644 index 0000000..08c7b47 --- /dev/null +++ b/templates/config/config.js.j2 @@ -0,0 +1,340 @@ +/* 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 also handled by NGINX, as documented in + * cryptpad/docs/example.nginx.conf (see the $main_domain variable) + * + */ + httpUnsafeOrigin: '{{ cryptpad_httpUnsafeOrigin }}', + +/* 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_httpSafeOrigin }}", + +/* 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: '{{ cryptpad_httpAddress }}', + +/* 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: {{ cryptpad_httpPort }}, + +/* 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: {{ cryptpad_httpSafePort }}, + +/* CryptPad will launch a child process for every core available + * in order to perform CPU-intensive tasks in parallel. + * Some host environments may have a very large number of cores available + * or you may want to limit how much computing power CryptPad can take. + * If so, set 'maxWorkers' to a positive integer. + */ + maxWorkers: {{ cryptpad_maxWorkers }}, + + /* ===================== + * 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 public signing + * key, which can be found on the settings page for registered users. + * Entries should be strings separated by a comma. + */ + + adminKeys: [ + "[{{ cryptpad_adminKeys }}]", + ], + + /* 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: {{ cryptpad_removeDonateButton }}, + + /* CryptPad will display a point of contact for your instance on its contact page + * (/contact.html) if you provide it below. + */ + adminEmail: '{{ cryptpad_adminEmail }}', + + /* + * 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: {{ cryptpad_blockDailyCheck }}, + + /* + * 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: {{ cryptpad_defaultStorageLimit }}, + + + /* ===================== + * 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: {{ cryptpad_inactiveTime }}, // 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: {{ cryptpad_archiveRetentionTime }}, + + /* It's possible to configure your instance to remove data + * stored on behalf of inactive accounts. Set 'accountRetentionTime' + * to the number of days an account can remain idle before its + * documents and other account data is removed. + * + * Leave this value commented out to preserve all data stored + * by user accounts regardless of inactivity. + */ + accountRetentionTime: {{ cryptpad_accountRetentionTime }}, + + /* Starting with CryptPad 3.23.0, the server automatically runs + * the script responsible for removing inactive data according to + * your configured definition of inactivity. Set this value to `true` + * if you prefer not to remove inactive data, or if you prefer to + * do so manually using `scripts/evict-inactive.js`. + */ + disableIntegratedEviction: {{ cryptpad_disableIntegratedEviction }}, + + + /* 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: {{ cryptpad_maxUploadSize }}, + + /* + * 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: { + "[cryptpad-user1@my.awesome.website/YZgXQxKR0Rcb6r6CmxHPdAGLVludrAF2lEnkbx1vVOo=]": { + limit: 20 * 1024 * 1024 * 1024, + plan: 'insider', + note: 'storage space donated by my.awesome.website' + }, + "[cryptpad-user2@my.awesome.website/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: {{ cryptpad_premiumUploadSize }}, + + /* ===================== + * 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: '{{ cryptpad_filePath }}', + + /* 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: '{{ cryptpad_archivePath }}', + + /* 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: '{{ cryptpad_pinPath }}', + + /* if you would like the list of scheduled tasks to be stored in + a custom location, change the path below: + */ + taskPath: '{{ cryptpad_taskPath }}', + + /* if you would like users' authenticated blocks to be stored in + a custom location, change the path below: + */ + blockPath: '{{ cryptpad_blockPath }}', + + /* CryptPad allows logged in users to upload encrypted files. Files/blobs + * are stored in a 'blob-store'. Set its location here. + */ + blobPath: '{{ cryptpad_blobPath }}', + + /* CryptPad stores incomplete blobs in a 'staging' area until they are + * fully uploaded. Set its location here. + */ + blobStagingPath: '{{ cryptpad_blobStagingPath }}', + + /* 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: '{{ cryptpad_logPath }}', + + /* ===================== + * Debugging + * ===================== */ + + /* CryptPad can log activity to stdout + * This may be useful for debugging + */ + logToStdout: {{ cryptpad_logToStdout }}, + + /* 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: '{{ cryptpad_logLevel }}', + + /* 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: {{ cryptpad_logFeedback }}, + + /* CryptPad supports verbose logging + * (false by default) + */ + verbose: {{ cryptpad_verbose }}, +}; diff --git a/templates/etc/systemd/system/cryptpad.service.j2 b/templates/etc/systemd/system/cryptpad.service.j2 new file mode 100644 index 0000000..258315e --- /dev/null +++ b/templates/etc/systemd/system/cryptpad.service.j2 @@ -0,0 +1,26 @@ +[Unit] +Description=CryptPad API server + +[Service] +ExecStart=/usr/bin/node {{ cryptpad_path }}/server.js +WorkingDirectory={{ cryptpad_path }} +Restart=always +# Restart service after 10 seconds if node service crashes +RestartSec=2 + +# Output to syslog +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=cryptpad +User={{ cryptpad_user }} +Group={{ cryptpad_group }} +# modify to match your working directory +Environment='PWD="{{ cryptpad_path }}"' + +# systemd sets the open file limit to 4000 unless you override it +# cryptpad stores its data with the filesystem, so you should increase this to match the value of `ulimit -n` +# or risk EMFILE errors. +LimitNOFILE={{ cryptpad_LimitNOFILE }} + +[Install] +WantedBy=multi-user.target