diff --git a/roles/server/linx/defaults/main.yml b/roles/server/linx/defaults/main.yml new file mode 100644 index 0000000..cf94297 --- /dev/null +++ b/roles/server/linx/defaults/main.yml @@ -0,0 +1,33 @@ +--- + +#domain: "lynx.localhost" + +binary_architecture: "linux-amd64" + +system_user: "{{ domain | regex_replace('[^A-Za-z0-9-]+', '-') }}" +service_name: "{{ domain }}.service" + +user_directory: "{{ global_webservers_directory }}/{{ domain }}" +installation_directory: "{{ user_directory }}/bin" +binary_path: "{{ installation_directory }}/linx-server" +configuration_directory: "{{ user_directory }}/configuration" +configuration_file: "{{ configuration_directory }}/config.ini" +auth_codes_file: "{{ configuration_directory }}/auth_codes" +data_directory: "{{ user_directory }}/data" +files_directory: "{{ data_directory }}/files" +meta_directory: "{{ data_directory }}/meta" +# TODO Bind to socket path +bind_port: 12840 +#!socket_directory: "{{ user_directory }}/socket" +#!socket_path: "{{ socket_directory }}/socket" + +auth_code: "{{ lookup('password', 'credentials/' + inventory_hostname + '/' + domain + '/auth_code chars=digits,ascii_letters length=80') }}" +force_random_filenames: no +max_size: "{{ 4 * 1024 * 1024 * 1024 }}" +max_expiry: 0 +site_name: "Linx {{ domain }}" +selif_path: "files" + +client_additional_body_size: "{{ 16 * 1024 }}" +client_max_body_size: "{{ max_size + client_additional_body_size }}" +update_script_path: "{{ update_scripts_directory }}/{{ domain }}" diff --git a/roles/server/linx/handlers/main.yml b/roles/server/linx/handlers/main.yml new file mode 100644 index 0000000..fb12ac5 --- /dev/null +++ b/roles/server/linx/handlers/main.yml @@ -0,0 +1,7 @@ +--- + +- name: restart linx + systemd: + state: restarted + name: "{{ service_name }}" + enabled: yes diff --git a/roles/server/linx/meta/main.yml b/roles/server/linx/meta/main.yml new file mode 100644 index 0000000..27182ea --- /dev/null +++ b/roles/server/linx/meta/main.yml @@ -0,0 +1,18 @@ +--- + +allow_duplicates: yes + +dependencies: + - role: misc/handlers + - role: misc/system_user + # system_user + # user_directory + user_directory_mode: "u=rx,g=rx,o=" + - role: misc/backup_files + # domain + backup_directory: "{{ data_directory }}" + - role: nginx/proxy + # domain + backend_port: "{{ bind_port }}" + additional_directives: | + client_max_body_size {{ client_max_body_size }}; diff --git a/roles/server/linx/tasks/main.yml b/roles/server/linx/tasks/main.yml new file mode 100644 index 0000000..44d42f0 --- /dev/null +++ b/roles/server/linx/tasks/main.yml @@ -0,0 +1,93 @@ +--- + +- name: Create required read only directories + file: + state: directory + path: "{{ item }}" + owner: "{{ system_user }}" + group: "{{ system_user }}" + mode: "u=rx,g=rx,o=" + loop: + - "{{ configuration_directory }}" + - "{{ installation_directory }}" + - "{{ data_directory }}" + +- name: Create required data directories + file: + state: directory + path: "{{ item }}" + owner: "{{ system_user }}" + group: "{{ system_user }}" + mode: "u=rwx,g=rx,o=" + loop: + - "{{ files_directory }}" + - "{{ meta_directory }}" +# - "{{ socket_directory }}" + +- name: Install auto update script for linx + template: + src: "update.sh" + dest: "{{ update_script_path }}" + owner: root + group: root + mode: "u=rwx,g=rx,o=r" + +- name: Download linx + command: "{{ update_script_path }}" + args: + chdir: "{{ installation_directory }}" + creates: "{{ binary_path }}" + notify: + - restart linx + +- name: Configure linx + template: + src: "config.ini" + dest: "{{ configuration_file }}" + owner: "{{ system_user }}" + group: "{{ system_user }}" + mode: "u=r,g=r,o=" + notify: + - restart linx + +# TODO Move to helper script +# TODO Implement proper change detection / renew hash on auth_code change +# TODO Set mode of resulting file correctly +- name: Create auth code file + file: + state: touch + path: "{{ auth_codes_file }}" + owner: "{{ system_user }}" + group: "{{ system_user }}" + mode: "u=rw,g=,o=" +- name: Register auth code for uploading to linx + become_user: "{{ system_user }}" + shell: >- + echo {{ auth_code | quote }} + | {{ installation_directory | quote }}/linx-genkey + | grep --only-matching --perl-regexp '(?<=\s)[^\s]+=' + > {{ auth_codes_file | quote }} + args: + chdir: "{{ user_directory }}" +# creates: "{{ auth_codes_file }}" + notify: + - restart linx + +- name: Register service for linx + template: + src: "linx.service" + dest: "{{ global_systemd_configuration_directory }}/{{ service_name }}" + owner: root + group: root + mode: "u=rw,g=r,o=" + notify: + - reload systemd + - restart linx + +- name: Enable auto update of linx + cron: + hour: 2 + minute: 0 + job: "{{ update_script_path }}" + name: "update linx for {{ domain }}" + state: present diff --git a/roles/server/linx/templates/config.ini b/roles/server/linx/templates/config.ini new file mode 100644 index 0000000..5893384 --- /dev/null +++ b/roles/server/linx/templates/config.ini @@ -0,0 +1,13 @@ +bind = 127.0.0.1:{{ bind_port }} +sitename = {{ site_name }} +siteurl = https://{{ domain }}/ +selifpath = {{ selif_path }} +maxsize = {{ max_size }} +maxexpiry = {{ max_expiry }} +realip = true +nologs = false +force-random-filename = {{ force_random_filenames | ternary('true', 'false') }} +authfile = {{ auth_codes_file }} +remoteauthfile = {{ auth_codes_file }} +filespath = {{ files_directory }} +metapath = {{ meta_directory }} diff --git a/roles/server/linx/templates/linx.service b/roles/server/linx/templates/linx.service new file mode 100644 index 0000000..a81939e --- /dev/null +++ b/roles/server/linx/templates/linx.service @@ -0,0 +1,24 @@ +[Unit] +Description=Linx on {{ domain }} +After=syslog.target +After=network.target + +[Service] +# Modify these two values and uncomment them if you have +# repos with lots of files and get an HTTP error 500 because +# of that +### +#LimitMEMLOCK=infinity +#LimitNOFILE=65535 +RestartSec=2s +Type=simple +User={{ system_user }} +Group={{ system_user }} +WorkingDirectory={{ installation_directory }} +ExecStart={{ binary_path | quote }} -config {{ configuration_file | quote }} +Restart=always +Environment="USER={{ system_user }}" +Environment="HOME={{ user_directory }}" + +[Install] +WantedBy=multi-user.target diff --git a/roles/server/linx/templates/update.sh b/roles/server/linx/templates/update.sh new file mode 100644 index 0000000..80af80d --- /dev/null +++ b/roles/server/linx/templates/update.sh @@ -0,0 +1,79 @@ +#!/bin/bash +set -euxo pipefail; + +# Constants +readonly ARCHITECTURE={{ binary_architecture | quote }}; +readonly BINARIES=( "cleanup" "genkey" "server" ); +readonly BIN_DIR={{ installation_directory | quote }}; +readonly PREFIX="linx"; +readonly SYSTEM_USER={{ system_user | quote }}; + +# Helper building filenames +function getFile() { + echo "$PREFIX-$2-$1_$ARCHITECTURE"; +} + +# Helper modifing owners and permissions +function correctPermissions() { + chown --no-dereference "root":"$SYSTEM_USER" "$1"; + chmod u=rwx,g=rx,o= "$1"; +} + +# Check newest version installed +installed="$( + (ls "$BIN_DIR" | + grep --only-matching --perl-regexp '(?<=-)v\d+(\.\d+)*(?=_)' | + sort --version-sort --reverse --unique | + head --lines=1) || + true +)"; + +# Check version from upstream +version="$( + curl --silent https://github.com/andreimarcu/linx-server/releases.atom | + grep --only-matching --perl-regexp '(?<=/releases/tag/)v\d+(\.\d+)*(?=")' | + head --lines=1 +)"; + +# Check for missing version numbers +if [[ -z "$installed" ]]; then + installed="v0"; +fi +if [[ -z "$version" ]]; then + error "Missing version available"; + exit 2; +fi + +# Check if version is already installed +if [[ "$installed" = "$version" ]]; then + exit 0; +fi + +# Remove version and redownloading (only applies on fallback) +for binary in "${BINARIES[@]}"; do + fileName="$(getFile "$version" "$binary")"; + filePath="$BIN_DIR/$fileName"; + url="https://github.com/andreimarcu/linx-server/releases/download/$version/$fileName"; + rm --force "$filePath"; + wget --quiet --output-document="$filePath" "$url"; + correctPermissions "$filePath"; +done + +# Relink new binaries +for binary in "${BINARIES[@]}"; do + toLinkPath="$BIN_DIR/$(getFile "$version" "$binary")"; + linkPath="$BIN_DIR/$PREFIX-$binary"; + ln --force --symbolic "$toLinkPath" "$linkPath"; + correctPermissions "$linkPath"; +done + +# Remove old version +for binary in "${BINARIES[@]}"; do + fileName="$(getFile "$installed" "$binary")"; + rm --force "$BIN_DIR/$fileName"; +done + +# Restart service +if systemctl is-enabled {{ service_name | quote }}; then + systemctl restart {{ service_name | quote }}; +fi