diff --git a/uwsgi-python/files/uwsgi.service b/uwsgi-python/files/uwsgi.service new file mode 100644 index 0000000000000000000000000000000000000000..21c602ae584c0c5b9c22ab345a588f8405e75e5e --- /dev/null +++ b/uwsgi-python/files/uwsgi.service @@ -0,0 +1,16 @@ +[Unit] +Description=uWSGI service unit +After=syslog.target + +[Service] +ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps/%I.ini +ExecReload=/bin/kill -HUP $MAINPID +ExecStop=/bin/kill -INT $MAINPID +Restart=always +Type=notify +StandardError=syslog +NotifyAccess=all +KillSignal=SIGQUIT + +[Install] +WantedBy=multi-user.target diff --git a/uwsgi-python/files/uwsgi.socket b/uwsgi-python/files/uwsgi.socket new file mode 100644 index 0000000000000000000000000000000000000000..641182e9ae065baad531f1ceac7d9f48fa81d1b4 --- /dev/null +++ b/uwsgi-python/files/uwsgi.socket @@ -0,0 +1,9 @@ +[Unit] +Description=Socket for uWSGI %I + +[Socket] +# Change this to your uwsgi application port or unix socket location +ListenStream=/run/uwsgi/%I.sock + +[Install] +WantedBy=sockets.target diff --git a/uwsgi-python/handlers/main.yml b/uwsgi-python/handlers/main.yml index c28bb7dd9f2d88756bf3f99a344f849d9946a905..62fb21298cec41102a99fec0dedb266b476b3cd8 100644 --- a/uwsgi-python/handlers/main.yml +++ b/uwsgi-python/handlers/main.yml @@ -3,3 +3,10 @@ - name: create tmpfiles command: systemd-tmpfiles --create + +- name: reload systemd service files + command: systemctl daemon-reload + +- name: restart uwsgi instance + service: name="uwsgi@{{ name }}" state=restarted + diff --git a/uwsgi-python/tasks/app.yml b/uwsgi-python/tasks/app.yml new file mode 100644 index 0000000000000000000000000000000000000000..b05c2a90f65e9cae8bb3f97abe2f93f35580f781 --- /dev/null +++ b/uwsgi-python/tasks/app.yml @@ -0,0 +1,207 @@ +--- + + +- name: ensure we have python 2 + apt: + name: "{{ item }}" + state: installed + with_items: + - python + - python-dev + - python-virtualenv + - uwsgi-plugin-python + - virtualenv + when: uwsgi_python == 2 + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have python 3 + apt: + name: "{{ item }}" + state: installed + with_items: + - python3 + - python3-dev + - python3-virtualenv + - uwsgi-plugin-python3 + - virtualenv + when: uwsgi_python == 3 + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have the necessary libraries for ldap + apt: + name: "{{ item }}" + state: installed + with_items: + - libsasl2-dev + - libssl-dev + - libldap2-dev + tags: + - uwsgi-app + - "{{ app_name }}" + +- include: sqlite.yml + when: app_db == "sqlite" + +- include: mysql.yml + when: app_db == "mysql" + +- include: postgres.yml + when: app_db == "postgres" + +- name: ensure we have a group + group: + name: "{{ app_group }}" + system: yes + state: present + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have a user + user: + name: "{{ app_user }}" + group: "{{ app_group }}" + system: yes + home: "{{ app_home }}" + shell: /usr/bin/nologin + createhome: no + state: present + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure a temporary directory exists + template: + src: tmpfiles.conf.j2 + dest: "/etc/tmpfiles.d/10-{{ app_name }}.conf" + owner: root + group: root + mode: 0644 + notify: + - create tmpfiles + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have our uwsgi config file + template: + src: uwsgi.ini.j2 + dest: "/etc/uwsgi/apps/{{ app_name }}.ini" + owner: root + group: root + mode: 0644 + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure additional software is installed + apt: name={{ item }} state=present + with_items: "{{ app_additional_software }}" + when: + - app_additional_software is defined + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure the deploy key is available + copy: + src: "{{ app_deploy_key }}" + dest: "/root/.ssh/{{ app_name }}" + owner: root + group: root + mode: 0600 + tags: + - uwsgi-app + - "{{ app_name }}" + +# https://github.com/ansible/ansible/issues/27699 +- name: ensure git module is able to clone + command: mount -o remount,exec /tmp + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have the program + git: + repo: "{{ app_git_url }}" + dest: "{{ app_path }}" + key_file: "/root/.ssh/{{ app_name }}" + version: "{{ app_git_version }}" + notify: + - restart uwsgi instance + register: git + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure git module is not able to clone anymore + command: mount -o remount,noexec /tmp + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have a virtualenv + pip: + requirements: "{{ app_path }}/requirements.txt" + virtualenv: "{{ app_venv }}" + virtualenv_python: "{{ app_python_version }}" + notify: + - restart uwsgi instance + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have our config + template: + src: "apps/{{ app_name }}.j2" + dest: "{{ app_path }}/{{ app_config_file }}" + owner: "{{ app_user }}" + group: "{{ app_group }}" + mode: 0640 + notify: + - restart uwsgi instance + tags: + - uwsgi-app + - "{{ app_name }}" + +- name: ensure we have our secret config + template: + src: secret_config.py.j2 + dest: "{{ app_path }}/secret_config.py" + owner: "{{ app_user }}" + group: "{{ app_group }}" + mode: 0600 + force: no + notify: + - restart uwsgi instance + tags: + - uwsgi-app + - "{{ app_name }}" + when: + - secret_config is defined + - secret_config == True + + +- include_tasks: "{{ item }}" + with_first_found: + - files: + - "apps/{{ app_name }}.yml" + skip: true + tags: + - uwsgi-app + - "{{ app_name }}" + +- meta: flush_handlers + +- name: ensure the service is enabled + service: + name: "uwsgi@{{ app_name }}" + enabled: yes + state: started + tags: + - uwsgi-app + - "{{ app_name }}" diff --git a/uwsgi-python/tasks/main.yml b/uwsgi-python/tasks/main.yml index f63c6bee3d5571e604cdb488579da634097e6616..c51f9d80600bcc0ef837692093ebe97efb6de8c5 100644 --- a/uwsgi-python/tasks/main.yml +++ b/uwsgi-python/tasks/main.yml @@ -1,99 +1,45 @@ --- # file: uwsgi-python/tasks/main.yml -- name: ensure we have python 2 - apt: - name: "{{ item }}" - state: installed - with_items: - - python - - python-dev - - python-virtualenv - - uwsgi-plugin-python - - virtualenv - when: uwsgi_python == 2 - tags: - - uwsgi-python - - webservices - -- name: ensure we have python 3 - apt: - name: "{{ item }}" - state: installed - with_items: - - python3 - - python3-dev - - python3-virtualenv - - uwsgi-plugin-python3 - - virtualenv - when: uwsgi_python == 3 - tags: - - uwsgi-python - - webservices -- name: ensure we have the necessary libraries for ldap +- name: ensure uwsgi is installed apt: - name: "{{ item }}" + name: uwsgi state: installed - with_items: - - libsasl2-dev - - libssl-dev - - libldap2-dev - tags: - - uwsgi-python - - webservices - -- include: sqlite.yml - when: uwsgi_db == "sqlite" - -- include: mysql.yml - when: uwsgi_db == "mysql" - -- include: postgres.yml - when: uwsgi_db == "postgres" - -- name: ensure we have a group - group: - name: "{{ uwsgi_group }}" - system: yes - state: present tags: - - uwsgi-python - - webservices - -- name: ensure we have a user - user: - name: "{{ uwsgi_user }}" - group: "{{ uwsgi_group }}" - system: yes - home: "{{ uwsgi_home }}" - shell: /usr/bin/nologin - createhome: no - state: present - tags: - - uwsgi-python + - uwsgi - webservices - name: ensure a temporary directory exists - template: - src: tmpfiles.conf.j2 - dest: "/etc/tmpfiles.d/10-{{uwsgi_name}}.conf" + copy: + src: tmpfiles.conf + dest: /etc/tmpfiles.d/10-uwsgi.conf owner: root group: root mode: 0644 notify: - create tmpfiles tags: - - uwsgi-python + - uwsgi - webservices -- name: ensure we have our uwsgi config file - template: - src: uwsgi.ini.j2 - dest: "/etc/uwsgi/apps-available/{{ uwsgi_name }}.ini" +- name: ensure we have archlinux's systemd-service file + copy: + src: uwsgi.service + dest: /etc/systemd/system/uwsgi.service owner: root group: root mode: 0644 tags: - - uwsgi-python + - uwsgi - webservices + +# TODO +# enthält webapps eine mehr-instanz-app mehrfach? wenn ja, ist ../vars/item.yml doof +# wenn nein, wie realisieren wir das? bsp: schildergenerator mit schilder, boxes +- include_tasks: app.yml + vars_files: + - "../vars/{{ item }}.yml" + - "{{ inventory_dir }}/vars/{{ item }}.yml" + with_items: "{{ webapps }}" + diff --git a/uwsgi-python/tasks/mysql.yml b/uwsgi-python/tasks/mysql.yml index 28bf42daf2d60a1fc8547c18e0a7320ddd70dbab..7dbaee953eb7c8374b83ef9fd4a143aa1e508c96 100644 --- a/uwsgi-python/tasks/mysql.yml +++ b/uwsgi-python/tasks/mysql.yml @@ -15,10 +15,10 @@ - name: ensure the mysql database exists mysql_db: - name: "{{ uwsgi_name }}" + name: "{{ app_name }}" state: present login_user: root - login_password: "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql create=true length=20')}}" + login_password: "{{ lookup('passwordstore', 'db/{{ansible_hostname}}-mysql create=true length=20') }}" no_log: True tags: - uwsgi-python @@ -26,12 +26,12 @@ - name: ensure the database user for mysql exists mysql_user: - name: "{{uwsgi_user}}" - password: "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql-{{uwsgi_user}} create=true length=20')}}" + name: "{{ app_user }}" + password: "{{ lookup('passwordstore', 'db/{{ansible_hostname}}-mysql-{{uwsgi_user}} create=true length=20') }}" state: present login_user: root login_password: "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql create=true length=20')}}" - priv: "{{uwsgi_name}}.*:ALL" + priv: "{{ app_name }}.*:ALL" no_log: True tags: - uwsgi-python diff --git a/uwsgi-python/tasks/postgres.yml b/uwsgi-python/tasks/postgres.yml index 5b0a5b5b8f7535f2f02ce5ce9f77d7dfe03f4d18..db8e7c1745adb41e6b6f2fad94cb5632dcfae895 100644 --- a/uwsgi-python/tasks/postgres.yml +++ b/uwsgi-python/tasks/postgres.yml @@ -3,7 +3,7 @@ - name: ensure we have a postgres database user postgresql_user: - name: "{{ uwsgi_user }}" + name: "{{ app_user }}" state: present become: yes become_user: postgres @@ -13,8 +13,8 @@ - name: ensure we have a postgres database postgresql_db: - name: "{{ uwsgi_name }}" - owner: "{{ uwsgi_user }}" + name: "{{ app_name }}" + owner: "{{ app_user }}" state: present become: yes become_user: postgres @@ -24,8 +24,8 @@ - name: ensure the database user has privileges postgresql_privs: - database: "{{ uwsgi_name }}" - roles: "{{ uwsgi_user }}" + database: "{{ app_name }}" + roles: "{{ app_user }}" privs: ALL state: present type: database diff --git a/uwsgi-python/templates/apps/shorturl.j2 b/uwsgi-python/templates/apps/shorturl.j2 new file mode 100644 index 0000000000000000000000000000000000000000..120054860c435c84e8757469d8019f365213e926 --- /dev/null +++ b/uwsgi-python/templates/apps/shorturl.j2 @@ -0,0 +1,34 @@ +from secret_config import secret_key as SECRET_KEY +SQLALCHEMY_DATABASE_URI = 'postgresql://{{ app_user }}:@/{{ app_name }}' +DEFAULT_REDIRECT = '{{ shorturl_default_redirect }}' +DEBUG = False +SESSION_COOKIE_SECURE = True + +import datetime +REMEMBER_COOKIE_NAME = 'remember_token' +REMEMBER_COOKIE_DURATION = datetime.timedelta(30) +REMEMBER_COOKIE_DOMAIN = None +REMEMBER_COOKIE_PATH = '/' +REMEMBER_COOKIE_SECURE = True +REMEMBER_COOKIE_HTTPONLY = True + +ADMIN_GROUP = '{{ shorturl_admin_group }}' +USER_GROUP = '{{ shorturl_user_group }}' + +AD_HOST = '{{ shorturl_ad_host }}' +AD_DOMAIN = '{{ shorturl_ad_domain }}' +AD_USER_DN = '{{ shorturl_ad_user_dn }}' +AD_GROUP_DN = '{{ shorturl_ad_group_dn }}' +AD_CA_CERT = '{{ shorturl_ad_cert }}' + +TARGET_REGEX = '{{ shorturl_target_regex }}' + +BRANDING_NAME = '{{ shorturl_branding_name }}' +BRANDING_DOMAIN = '{{ shorturl_branding_domain }}' +BRANDING_DOMAIN_REGEX = '{{ shorturl_branding_domain_regex }}' +BRANDING_CONTACT = '{{ shorturl_branding_contact }}' + +MAIL_SUBJECT = '{{ shorturl_mail_subject }}' +MAIL_DOMAIN = '{{ shorturl_mail_domain }}' +MAIL_ADMIN = '{{ shorturl_mail_admin }}' +MAIL_HOST = '{{ shorturl_mail_host }}' diff --git a/uwsgi-python/templates/tmpfiles.conf.j2 b/uwsgi-python/templates/tmpfiles.conf.j2 index 4dba06e9a3e556ed71bf92bee0797c52c9b521af..56b850cf47e762cabc3ba07077c90be5bc410f8d 100644 --- a/uwsgi-python/templates/tmpfiles.conf.j2 +++ b/uwsgi-python/templates/tmpfiles.conf.j2 @@ -1 +1 @@ -d /run/uwsgi/app/{{uwsgi_name}} 0775 {{uwsgi_user}} {{uwsgi_group}} - - +d /run/uwsgi/{{uwsgi_name}} 0775 {{uwsgi_user}} {{uwsgi_group}} - - diff --git a/uwsgi-python/templates/uwsgi.ini.j2 b/uwsgi-python/templates/uwsgi.ini.j2 index 8337e3cc11f983f05373ed19d28dcf2a7b586cbd..b4a1e55b7debdcca90766813008fb156b7b2a4af 100644 --- a/uwsgi-python/templates/uwsgi.ini.j2 +++ b/uwsgi-python/templates/uwsgi.ini.j2 @@ -1,8 +1,8 @@ [uwsgi] -uwsgi-socket = /run/uwsgi/app/{{uwsgi_name}}/{{uwsgi_name}}.sock +uwsgi-socket = /run/uwsgi/{{app_name}}/{{app_name}}.sock #http = localhost:5000 chmod-socket = 660 -chown-socket = {{uwsgi_user}}:www-data +chown-socket = {{app_user}}:www-data autoload = master = processes = 4 @@ -23,19 +23,16 @@ enable-threads = mule = {% endfor %} #umask = 227 -chdir = {{uwsgi_path}} -uid = {{uwsgi_user}} -gid = {{uwsgi_group}} -logto = /var/log/uwsgi/{{uwsgi_name}}.log -logfile-chown = {{uwsgi_user}}:{{uwsgi_group}} -logfile-chmod = 664 +chdir = {{app_path}} +uid = {{app_user}} +gid = {{app_group}} log-date = log-4xx = log-5xx = log-x-forwarded-for = -{% if uwsgi_python == 2 %} +{% if app_python_version == 2 %} plugin = python27 -{% elif uwsgi_python == 3 %} +{% elif app_python_version == 3 %} {% if debian_version == "jessie" %} plugin = python34 {% elif debian_version == "stretch" %} @@ -46,9 +43,9 @@ plugin = {{uwsgi_python_plugin|mandatory}}{# or add new debian versions here #} {% else %} plugin = {{uwsgi_python_plugin|mandatory}}{# or add new python versions here #} {% endif %} -virtualenv = {{uwsgi_venv|default(uwsgi_path)}} -wsgi-file = {{uwsgi_path}}/{{uwsgi_program}} -callable = {{uwsgi_callable}} -pyargv = {{uwsgi_program}} {{uwsgi_command}} +virtualenv = {{app_venv|default(app_path)}} +wsgi-file = {{app_path}}/{{app_program}} +callable = {{uapp_callable}} +pyargv = {{app_program}} {{app_command}} manage-script-name = -mount={{uwsgi_mountpoint}}={{uwsgi_path}}/{{uwsgi_program}} +mount={{app_mountpoint}}={{app_path}}/{{app_program}} diff --git a/uwsgi-python/tmpfiles.conf b/uwsgi-python/tmpfiles.conf new file mode 100644 index 0000000000000000000000000000000000000000..50b2862b7b5bfbdf7fafd0f4e6a54f0280e8c743 --- /dev/null +++ b/uwsgi-python/tmpfiles.conf @@ -0,0 +1,2 @@ +d /run/uwsgi 0755 root root - - +d /run/uwsgi/app 0755 root root - - diff --git a/uwsgi-python/vars/shorturl.yml b/uwsgi-python/vars/shorturl.yml new file mode 100644 index 0000000000000000000000000000000000000000..13e4ce9a1c886d3c59763be778cd0f08682031e6 --- /dev/null +++ b/uwsgi-python/vars/shorturl.yml @@ -0,0 +1,42 @@ +app_name: shorturl +app_user: shortlinks +app_group: shortlinks +app_home: /var/www/shorturl +app_path: /var/www/shorturl +app_python_version: 3 +app_venv: /var/www/shorturl/venv +app_program: shorturl.py +app_callable: app +app_command: "" +app_mountpoint: / + +app_db_type: postgres + +app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/shorturl" +app_git_url: "git@git.fsmpi.rwth-aachen.de:infra/shorturl.git" +app_git_version: HEAD + +app_config_file: config.py +app_secret_config: true + +shorturl_default_redirect: "https://www.example.com" +shorturl_admin_group: admin +shorturl_user_group: users + +shorturl_ad_host: 'ad.example.com' +shorturl_ad_domain: 'EXAMPLE' +shorturl_ad_user_dn: "cn=users,dc=example,dc=com" +shorturl_ad_group_dn: "cn=users,dc=example,dc=com" +shorturl_ad_cacert: "/etc/ssl/certs/example_cacert.pem" + +shorturl_target_regex: '^https://([a-zA-Z0-9-]+\.)*example\.com(/(.*))?$' +shorturl_branding_name: 'Example' +shorturl_branding_domain: 'short.example' +shorturl_branding_domain_regex: '^(?!(https?://)?(www\.)?(short\.example)/?)(.*)' +shorturl_branding_contact: 'contact@example.com' + +shorturl_mail_subject: 'confirmation request ShortURL service' +shorturl_mail_domain: 'example.com' +shorturl_mail_admin: 'contact@example.com' +shorturl_mail_host: 'mail.example.com' + diff --git a/uwsgi-python/vars/template.yml b/uwsgi-python/vars/template.yml new file mode 100644 index 0000000000000000000000000000000000000000..9b8b8ce060edd93235faf88376540afb9d91d5b4 --- /dev/null +++ b/uwsgi-python/vars/template.yml @@ -0,0 +1,28 @@ +name: +user +group +home +path +python_version +venv +program = server.py +callable = app +command +mountpoint + +db_type + + + +uwsgi_options +uwsgi_harakiri +uwsgi_mules +uwsgi_enable_threads + +app_deploy_key +app_git_url +app_git_version + +config_file +secret_config = T/F +