From 216deda9167aac2981c384ace07f04e4d62ba5d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C5=A1per=20Fele-=C5=BDor=C5=BE?= Date: Thu, 23 Oct 2025 20:32:48 +0200 Subject: [PATCH] Add role for apis-rilec --- roles/rilec/files/motd | 1 + roles/rilec/files/uwsgi.ini | 2 + roles/rilec/handlers/main.yml | 17 ++ roles/rilec/meta/main.yml | 2 + roles/rilec/tasks/main.yml | 174 ++++++++++++++++++ roles/rilec/templates/apis-rilec.ini.j2 | 32 ++++ roles/rilec/templates/apis_process_data.sh.j2 | 4 + roles/rilec/templates/environment.j2 | 36 ++++ roles/rilec/templates/nginx.conf.j2 | 25 +++ 9 files changed, 293 insertions(+) create mode 100644 roles/rilec/files/motd create mode 100644 roles/rilec/files/uwsgi.ini create mode 100644 roles/rilec/handlers/main.yml create mode 100644 roles/rilec/meta/main.yml create mode 100644 roles/rilec/tasks/main.yml create mode 100644 roles/rilec/templates/apis-rilec.ini.j2 create mode 100644 roles/rilec/templates/apis_process_data.sh.j2 create mode 100644 roles/rilec/templates/environment.j2 create mode 100644 roles/rilec/templates/nginx.conf.j2 diff --git a/roles/rilec/files/motd b/roles/rilec/files/motd new file mode 100644 index 0000000..7e7f96a --- /dev/null +++ b/roles/rilec/files/motd @@ -0,0 +1 @@ +Apis rilec. Glug glug, njam njam. diff --git a/roles/rilec/files/uwsgi.ini b/roles/rilec/files/uwsgi.ini new file mode 100644 index 0000000..275e85e --- /dev/null +++ b/roles/rilec/files/uwsgi.ini @@ -0,0 +1,2 @@ +[uwsgi] +emperor = /etc/uwsgi/conf.d diff --git a/roles/rilec/handlers/main.yml b/roles/rilec/handlers/main.yml new file mode 100644 index 0000000..220a2eb --- /dev/null +++ b/roles/rilec/handlers/main.yml @@ -0,0 +1,17 @@ +- name: reload nginx + service: + name: nginx + state: reloaded + when: "'handler' not in ansible_skip_tags" + +- name: reload uwsgi + service: + name: uwsgi + state: reloaded + when: "'handler' not in ansible_skip_tags" + +- name: restart uwsgi + service: + name: uwsgi + state: restarted + when: "'handler' not in ansible_skip_tags" diff --git a/roles/rilec/meta/main.yml b/roles/rilec/meta/main.yml new file mode 100644 index 0000000..69891c7 --- /dev/null +++ b/roles/rilec/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - role: nginx diff --git a/roles/rilec/tasks/main.yml b/roles/rilec/tasks/main.yml new file mode 100644 index 0000000..9c9668c --- /dev/null +++ b/roles/rilec/tasks/main.yml @@ -0,0 +1,174 @@ +- name: Install dependencies + package: + name: + - git + - python3 + - python3-dev + - py3-pip + - py3-virtualenv + - bash # for upgrade script + - build-base # to build psycopg if not available + - postgresql-dev # likewise + - uwsgi + - uwsgi-python3 + - openldap-dev + +- name: Create group for web service + group: + name: '{{ user }}' + system: yes + +- name: Create user for web service + user: + name: '{{ user }}' + group: '{{ user }}' + home: '/srv/{{ user }}' + shell: /bin/sh + system: yes + register: user_info + +- name: Clone web files + become: yes + become_user: "{{ user }}" + become_method: su + become_flags: "-s /bin/sh" + git: + repo: 'https://github.com/polz113/apis-ad-rilec' + dest: "{{ user_info.home }}/apis-rilec" + force: yes + notify: reload uwsgi + +- name: Set django_app + set_fact: + django_app: "{{ user_info.home }}/apis-rilec/python/django/apis_rilec_fri/" + django_venv: "{{ user_info.home }}/venv/apis-rilec/" + public_root: "{{ user_info.home }}/www_data/apis-rilec/" + +- name: Create directory for static files + file: + state: directory + owner: "{{ user }}" + path: "{{ public_root }}/static" + +- name: Create directory for media + file: + state: directory + owner: "{{ user }}" + path: "{{ public_root }}/media" + +- name: Install requirements + become: yes + become_user: "{{ user }}" + become_method: su + become_flags: '-s /bin/sh' + pip: + requirements: "{{ django_app }}/requirements.txt" + virtualenv: "{{ django_venv }}" + notify: restart uwsgi + +- name: Install database driver + become: yes + become_user: "{{ user }}" + become_method: su + become_flags: '-s /bin/sh' + pip: + name: "psycopg" + virtualenv: "{{ django_venv }}" + notify: restart uwsgi + +- name: Configure settings + template: + dest: "{{ django_app }}/apis_rilec_fri/.env" + src: "environment.j2" + owner: apis + group: apis + mode: 0600 + force: yes + notify: restart uwsgi + +- name: Run migrations + become: yes + become_user: '{{ user }}' + command: + cmd: '{{ django_venv }}/bin/python {{ django_app }}/manage.py migrate --noinput' + +- name: Collect static files + command: + cmd: '{{ django_venv }}/bin/python {{ django_app }}/manage.py collectstatic --noinput' + +- name: Create superuser / set password + become: yes + become_user: '{{ user }}' + command: + cmd: '{{ django_venv }}/bin/python {{ django_app }}/manage.py shell --interface python' + stdin: | + import sys + from django.contrib.auth.models import User + username = '{{ password.admin_user }}' + u, created = User.objects.get_or_create(username=username) + u.set_password('{{ password.admin_pass }}') + u.is_staff = True + u.is_superuser = True + u.save() + register: result + +#- name: Create admin user +# shell: ". {{django_venv}}/bin/activate; cd {{ django_app }}; ./manage.py createsuperuser --noinput" + +- name: Configure uwsgi + copy: + dest: /etc/uwsgi/ + src: uwsgi.ini + notify: restart uwsgi + +- name: Configure uwsgi instance + template: + dest: /etc/uwsgi/conf.d/apis-rilec.ini + src: apis-rilec.ini.j2 + owner: apis + group: apis + +- name: Enable uwsgi + service: + name: uwsgi + enabled: yes + state: started + +- name: Configure nginx instance + template: + dest: /etc/nginx/http.d/apis-rilec.conf + src: nginx.conf.j2 + notify: reload nginx + +- name: Process data every day + cron: + name: "delete data older than 1 month" + job: ". {{django_venv}}/bin/activate; cd {{ django_app }}; ./manage.py clean -d 32" + user: apis + hour: "02" + minute: "15" + +- name: Create data update script + template: + dest: "{{ user_info.home }}/apis_process_data.sh" + src: apis_process_data.sh.j2 + mode: 0775 + owner: apis + group: apis + +- name: Periodically update data + cron: + name: "Process data from apis" + job: "{{ user_info.home }}/rilec_process_data.sh" + user: apis + hour: "19,7" + minute: "00" + +- name: Periodically delete data older than 1 month + cron: + name: "delete data older than 1 month" + job: ". {{django_venv}}/bin/activate; cd {{ django_app }}; ./manage.py clean -d 32" + user: apis + hour: "02" + minute: "15" + diff --git a/roles/rilec/templates/apis-rilec.ini.j2 b/roles/rilec/templates/apis-rilec.ini.j2 new file mode 100644 index 0000000..0f1dfe3 --- /dev/null +++ b/roles/rilec/templates/apis-rilec.ini.j2 @@ -0,0 +1,32 @@ +[uwsgi] +plugin = python3 + +uid = {{ user }} +gid = {{ user }} + +# the socket (use the full path to be safe +socket = /run/apis-rilec.socket +chown-socket = {{ user }}:nginx +chmod-socket = 660 + +# log +logto = /var/log/uwsgi/apis-rilec/apis-rilec.log + +# Django-related settings +# the base directory (full path) +chdir = {{ django_app }} +# Django's wsgi file +module = apis_rilec_fri.wsgi +# the virtualenv (full path) +home = {{ django_venv }} + +# process-related settings +# master +master = true +# maximum number of worker processes +processes = 16 +harakiri = 3600 +# clear environment on exit +vacuum = true + + diff --git a/roles/rilec/templates/apis_process_data.sh.j2 b/roles/rilec/templates/apis_process_data.sh.j2 new file mode 100644 index 0000000..ea86b25 --- /dev/null +++ b/roles/rilec/templates/apis_process_data.sh.j2 @@ -0,0 +1,4 @@ +#!/bin/sh +. {{ django_venv }}/bin/activate +{{ django_app }}/manage.py from_ldap +{{ django_app }}/manage.py to_ldapobjects -gs -cd diff --git a/roles/rilec/templates/environment.j2 b/roles/rilec/templates/environment.j2 new file mode 100644 index 0000000..fbd0e2e --- /dev/null +++ b/roles/rilec/templates/environment.j2 @@ -0,0 +1,36 @@ +DEBUG=false +# DATABASE_URL="mysql://apisrilec:TestBazeZaApisRilec@127.0.0.1:3306/apisrilecphp" +DATABASE_URL="postgresql://{{ user }}@localhost/{{database | default(user)}}" +# mysql://USER:PASSWORD@HOST:PORT/NAME +ALLOWED_HOSTS=apis-rilec.fri.uni-lj.si,apis-rilec.fri1.uni-lj.si,apis-rilec-php.fri1.uni-lj.si +SECRET_KEY="{{ password.secret_key }}" +PUBLIC_ROOT={{ user_info.home }}/www_data/apis-rilec + +# APIS_X_API_KEY="ToleJeSkrivnost" +X_API_KEY="{{ password.x_api_key }}" + +STUDIS_API_TOKEN="{{ password.studis_api_token }}" +STUDIS_API_BASE_URL=https://studisfri.uni-lj.si/api + +#LDAP_SERVER_URI="ldap://212.235.188.28:389" +# LDAP_SERVER_URI="ldap://dcv1fri1.fri1.uni-lj.si:389" +# LDAP_BIND_DN="CN=ldap test,OU=ServiceAccounts,DC=test,DC=nodomain", +# LDAP_BIND_DN="CN=LDAP\\, RILEC,OU=System,OU=admin,DC=fri1,DC=uni-lj,DC=si" +# LDAP_BIND_PASSWORD="rUn.n-9pNUMq>7[}{AAF2W)f" + + +LDAP_SERVER_URI="{{ ldap_server }}" +LDAP_BIND_DN="{{ password.ldap_bind_dn }}" +LDAP_BIND_PASSWORD="{{ password.ldap_bind_pass }}" +LDAP_USER_SEARCH_BASE="OU=FRI,DC=fri1,DC=uni-lj,DC=si" +LDAP_USER_SEARCH_SCOPE="SUBTREE" +LDAP_START_TLS=true +LDAP_OPT_X_TLS_REQUIRE_CERT="NEVER" + +# AUTH_LDAP_USER_DN_TEMPLATE = "userPrincipalName=%(user)s,OU=Users,OU=FRI,DC=fri1,DC=uni-lj,DC=si" + +LDAP_GROUP_SEARCH_BASE="OU=FRI,DC=fri1,DC=uni-lj,DC=si" +AUTH_LDAP_MIRROR_GROUPS=true +AUTH_LDAP_ALWAYS_UPDATE_USER=true +AUTH_LDAP_CACHE_GROUPS=true +AUTH_LDAP_GROUP_CACHE_TIMEOUT=3600 diff --git a/roles/rilec/templates/nginx.conf.j2 b/roles/rilec/templates/nginx.conf.j2 new file mode 100644 index 0000000..45f09fd --- /dev/null +++ b/roles/rilec/templates/nginx.conf.j2 @@ -0,0 +1,25 @@ +server { + listen 443 ssl; + listen [::]:443 ssl; + server_name {{ dns_name }}; + + ssl_certificate /etc/letsencrypt/live/{{ dns_name }}/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/{{ dns_name }}/privkey.pem; + + location @uwsgi { + include uwsgi_params; + uwsgi_pass unix:/run/apis-rilec.socket; + } + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + alias {{ public_root }}; + try_files $uri @uwsgi; + } + location /media/ { + alias {{ public_root }}/media/; + } + location /static/ { + alias {{ public_root }}/static/; + } +}