diff --git a/.env.sample b/.env.sample index 71583f9d..6c40dddc 100644 --- a/.env.sample +++ b/.env.sample @@ -7,8 +7,8 @@ HOSTNAME=localhost:8000 CSRF_COOKIE_DOMAIN=.mysite.com # Postgres database credentials -DB_NAME=webapp -DB_USER=webapp +DB_NAME=gms +DB_USER=gms DB_PASSWORD="secret" # Credentials for your SMTP mail server @@ -16,6 +16,9 @@ MAIL_FROM_ADDRESS=noreply@mysite.com MAIL_TO_ADDRESS=helpdesk@mysite.com MAIL_USE_TLS=true +# Optional: Send error emails to a different address than MAIL_FROM_ADDRESS +SERVER_EMAIL=support@mysite.com + MAIL_SMTP_PORT=25 MAIL_HOSTNAME=mail.mysite.com MAIL_SMTP_USERNAME=admin diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 0861a78b..2747f985 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -23,6 +23,6 @@ jobs: echo "${{ secrets.SSH_PRIVATE_KEY_DEV }}" > ~/.ssh/id_rsa ssh-keyscan -H ${{ secrets.SSH_HOST_DEV }} > ~/.ssh/known_hosts - name: connect and pull - run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST_DEV }} "./update.sh && exit" + run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST_DEV }} "sudo ./update.sh && exit" - name: cleanup run: rm -rf ~/.ssh diff --git a/deploy/ansible/.gitignore b/deploy/ansible/.gitignore index a4d3d49a..793cd85d 100644 --- a/deploy/ansible/.gitignore +++ b/deploy/ansible/.gitignore @@ -1,2 +1,2 @@ roles/* -!roles/webapp \ No newline at end of file +!roles/galaxy_media_site \ No newline at end of file diff --git a/deploy/ansible/README.md b/deploy/ansible/README.md index f5a501b0..649902ec 100644 --- a/deploy/ansible/README.md +++ b/deploy/ansible/README.md @@ -37,7 +37,7 @@ python -m pip install ansible - *Optional* - Host installation paths: - `project_root` - where this git repository will be cloned - `server_root` - where server configuration will be saved - - `web_root` - where the application will be served from + - `django_root` - where the application will be served from - `venv_root` - where the virtual env will be created diff --git a/deploy/ansible/dev.yml b/deploy/ansible/dev.yml index 2664227b..d3f28a96 100644 --- a/deploy/ansible/dev.yml +++ b/deploy/ansible/dev.yml @@ -6,7 +6,10 @@ - group_vars/secrets.yml - group_vars/webservers.yml roles: - - geerlingguy.nginx + - role: geerlingguy.nginx + tags: init - role: geerlingguy.postgresql become: true - - webapp + tags: init,postgresql + - role: galaxy_media_site + tags: gms diff --git a/deploy/ansible/files/webapp.socket b/deploy/ansible/files/webapp.socket index 4eb3bbe1..094d1e5c 100644 --- a/deploy/ansible/files/webapp.socket +++ b/deploy/ansible/files/webapp.socket @@ -1,6 +1,6 @@ [Unit] Description=Galaxy content site socket [Socket] -ListenStream=/run/webapp.sock +ListenStream=/run/gms.sock [Install] WantedBy=sockets.target diff --git a/deploy/ansible/group_vars/webservers.yml b/deploy/ansible/group_vars/webservers.yml index 42630787..35488d7f 100644 --- a/deploy/ansible/group_vars/webservers.yml +++ b/deploy/ansible/group_vars/webservers.yml @@ -16,8 +16,8 @@ gunicorn: web_workers: 4 # Postgres database conf -postgres_db_name: webapp -postgres_db_user: webapp +postgres_db_name: gms +postgres_db_user: gms postgresql_locales: - 'en_US.UTF-8' @@ -30,6 +30,7 @@ postgresql_users: - name: "{{ postgres_db_user }}" password: "{{ postgres_db_password }}" db: "{{ postgres_db_name }}" + priv: ALL postgres_users_no_log: false @@ -37,18 +38,18 @@ postgres_users_no_log: false # ----------------------------------------------------------------------------- # Will git clone galaxy-content-site to here -project_root: /home/ubuntu/galaxy-content-site +project_root: /srv/sites/galaxy-media-site # This is where service files will be created -server_root: /home/ubuntu/serve +server_root: /srv/config # App will be served from here -web_root: /srv/webapp +django_root: "{{ project_root }}/webapp" # Virtual environment will be created here -venv_root: "{{ project_root }}/.venv" +venv_root: "{{ project_root }}/venv" -# Admin user login for the admin portal +# Login for django admin portal admin_user: first_name: admin last_name: admin diff --git a/deploy/ansible/group_vars/webservers.yml.sample b/deploy/ansible/group_vars/webservers.yml.sample index 8ec68d6c..aa1ecb17 100644 --- a/deploy/ansible/group_vars/webservers.yml.sample +++ b/deploy/ansible/group_vars/webservers.yml.sample @@ -19,8 +19,8 @@ gunicorn: web_workers: 4 # Postgres database conf -postgres_db_name: webapp -postgres_db_user: webapp +postgres_db_name: gms +postgres_db_user: gms postgresql_locales: - 'en_US.UTF-8' @@ -46,7 +46,7 @@ project_root: /home/ubuntu/galaxy-content-site server_root: /home/ubuntu/serve # App will be served from here -web_root: /srv/webapp +django_root: /srv/webapp # Virtual environment will be created here venv_root: "{{ project_root }}/.venv" diff --git a/deploy/ansible/host_vars/site.usegalaxy.org.au.yml b/deploy/ansible/host_vars/site.usegalaxy.org.au.yml deleted file mode 100644 index edaf9995..00000000 --- a/deploy/ansible/host_vars/site.usegalaxy.org.au.yml +++ /dev/null @@ -1 +0,0 @@ -hostname: usegalaxy-au.neoformit.com diff --git a/deploy/ansible/hosts b/deploy/ansible/hosts index 52e97fbb..c99064c0 100644 --- a/deploy/ansible/hosts +++ b/deploy/ansible/hosts @@ -1,5 +1,5 @@ [webservers] -site.usegalaxy.org.au ansible_connection=ssh ansible_user=ubuntu +site.usegalaxy.org.au ansible_connection=ssh ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/galaxy [dev_webservers] -dev-site.gvl.org.au ansible_connection=ssh ansible_user=ubuntu +dev-site.gvl.org.au ansible_connection=ssh ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/galaxy diff --git a/deploy/ansible/prod.yml b/deploy/ansible/prod.yml index 938695bb..8c74c6d3 100644 --- a/deploy/ansible/prod.yml +++ b/deploy/ansible/prod.yml @@ -6,7 +6,10 @@ - group_vars/secrets.yml - group_vars/webservers.yml roles: - - geerlingguy.nginx + - role: geerlingguy.nginx + tags: init - role: geerlingguy.postgresql become: true - - webapp + tags: init,postgresql + - role: galaxy_media_site + tags: gms diff --git a/deploy/ansible/roles/webapp/defaults/main.yml b/deploy/ansible/roles/galaxy_media_site/defaults/main.yml similarity index 67% rename from deploy/ansible/roles/webapp/defaults/main.yml rename to deploy/ansible/roles/galaxy_media_site/defaults/main.yml index edcbd089..f1127c1e 100644 --- a/deploy/ansible/roles/webapp/defaults/main.yml +++ b/deploy/ansible/roles/galaxy_media_site/defaults/main.yml @@ -1,15 +1,15 @@ --- -project_root: /home/ubuntu/galaxy-content-site -server_root: /home/ubuntu/server -web_root: /srv/webapp +project_root: /srv/galaxy-media-site +server_root: /srv/config +django_root: "{{ project_root }}/webapp" venv_root: "{{ project_root }}/venv" -webapp: +gms: templates: - src: "{{ role_path }}/templates/gunicorn.py.j2" dest: "{{ server_root }}/gunicorn.py" - - src: "{{ role_path }}/templates/webapp.service.j2" - dest: /etc/systemd/system/webapp.service + - src: "{{ role_path }}/templates/gms.service.j2" + dest: /etc/systemd/system/gms.service - src: "{{ role_path }}/templates/setup.sh.j2" dest: "{{ server_root }}/setup.sh" - src: "{{ role_path }}/templates/nginx.vhost.j2" @@ -20,8 +20,8 @@ webapp: dest: "/home/ubuntu/update.sh" files: - - src: "{{ role_path }}/files/webapp.socket" - dest: /etc/systemd/system/webapp.socket + - src: "{{ role_path }}/files/gms.socket" + dest: /etc/systemd/system/gms.socket certbot_ssl: true diff --git a/deploy/ansible/roles/webapp/files/webapp.socket b/deploy/ansible/roles/galaxy_media_site/files/gms.socket similarity index 74% rename from deploy/ansible/roles/webapp/files/webapp.socket rename to deploy/ansible/roles/galaxy_media_site/files/gms.socket index 4eb3bbe1..094d1e5c 100644 --- a/deploy/ansible/roles/webapp/files/webapp.socket +++ b/deploy/ansible/roles/galaxy_media_site/files/gms.socket @@ -1,6 +1,6 @@ [Unit] Description=Galaxy content site socket [Socket] -ListenStream=/run/webapp.sock +ListenStream=/run/gms.sock [Install] WantedBy=sockets.target diff --git a/deploy/ansible/roles/webapp/tasks/main.yml b/deploy/ansible/roles/galaxy_media_site/tasks/main.yml similarity index 64% rename from deploy/ansible/roles/webapp/tasks/main.yml rename to deploy/ansible/roles/galaxy_media_site/tasks/main.yml index ac5f719e..03335ba1 100644 --- a/deploy/ansible/roles/webapp/tasks/main.yml +++ b/deploy/ansible/roles/galaxy_media_site/tasks/main.yml @@ -1,5 +1,15 @@ --- +- name: Check whether SSL certificate is already installed + ansible.builtin.shell: "certbot certificates" + register: certbot_certificates + changed_when: false + +- name: Set ssl_cert_exists fact from certbot output + ansible.builtin.set_fact: + ssl_cert_exists: "{{ true if inventory_hostname in certbot_certificates.stdout else false }}" + changed_when: false + - name: create server directory file: path: "{{ server_root }}" @@ -19,11 +29,19 @@ name: - gcc - python3.12 - - python3.12-pip - - python3.12-venv + - python3-pip + - python3-virtualenv - python3.12-dev - python3-certbot-nginx +- name: Grant database privileges to postgres_db_user + ansible.builtin.shell: > + sudo -u postgres psql -c + "GRANT ALL ON SCHEMA public TO {{ postgres_db_user }}; + GRANT USAGE, CREATE ON SCHEMA public TO {{ postgres_db_user }}; + ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO gms;" + become: yes + - name: clone git repository for galaxy-content-site ansible.builtin.git: repo: https://github.com/neoformit/galaxy-content-site.git @@ -31,33 +49,27 @@ clone: yes force: yes -- name: link webapp to /srv/sites - ansible.builtin.file: - src: "{{ project_root }}/webapp" - dest: "{{ web_root }}" - state: link - -- name: create webapp media directory +- name: create gms media directory file: - path: "{{ web_root }}/webapp/media" + path: "{{ django_root }}/webapp/media" state: directory -- name: create webapp logs directory +- name: create gms logs directory file: - path: "{{ web_root }}/webapp/logs" + path: "{{ django_root }}/webapp/logs" state: directory - name: template webserver configuration template: src: "{{ item.src }}" dest: "{{ item.dest }}" - loop: "{{ webapp.templates }}" + loop: "{{ gms.templates }}" - name: copy webserver configuration copy: src: "{{ item.src }}" dest: "{{ item.dest }}" - loop: "{{ webapp.files }}" + loop: "{{ gms.files }}" - name: link to enable nginx virtualhost ansible.builtin.file: @@ -71,16 +83,16 @@ virtualenv: "{{ venv_root }}" virtualenv_python: python3.12 -- name: run webapp setup script +- name: run gms setup script command: "bash {{ server_root }}/setup.sh" - name: create and install SSL certificate with letsencrypt command: "certbot --nginx --noninteractive --agree-tos --redirect --email {{ certbot_renew_email }} -d {{ inventory_hostname }}" when: certbot_ssl -- name: Ensure webapp superuser login +- name: Ensure gms superuser login shell: | - cd {{ web_root }} && \ + cd {{ django_root }} && \ export DJANGO_SUPERUSER_PASSWORD={{ admin_user.password }} && \ {{ venv_root }}/bin/python manage.py createsuperuser --noinput \ --email {{ admin_user.email }} \ @@ -98,10 +110,10 @@ group: ubuntu - name: update media file ownership - file: dest={{ web_root }}/webapp/media owner=www-data group=www-data mode=u=rwX,g=rwX,o=rwX recurse=yes + file: dest={{ django_root }}/webapp/media owner=www-data group=www-data mode=u=rwX,g=rwX,o=rwX recurse=yes - name: update log file ownership - file: dest={{ web_root }}/webapp/logs owner=www-data group=www-data mode=u=rwX,g=rwX,o=rwX recurse=yes + file: dest={{ django_root }}/webapp/logs owner=www-data group=www-data mode=u=rwX,g=rwX,o=rwX recurse=yes - name: make update.sh executable file: dest=/home/ubuntu/update.sh mode=a+x @@ -109,7 +121,7 @@ - name: check whether news scraper in GMS version ansible.builtin.shell: "{{ venv_root }}/bin/python manage.py scrape_news --help" args: - chdir: "{{ web_root }}" + chdir: "{{ django_root }}" register: check_scraper - name: add cron job to scrape news feed @@ -118,5 +130,5 @@ user: ubuntu hour: 9 minute: 0 - job: "cd {{ web_root }} && {{ venv_root }}/bin/python manage.py scrape_news" + job: "cd {{ django_root }} && {{ venv_root }}/bin/python manage.py scrape_news" when: check_scraper.rc == 0 diff --git a/deploy/ansible/roles/webapp/templates/.env.j2 b/deploy/ansible/roles/galaxy_media_site/templates/.env.j2 similarity index 100% rename from deploy/ansible/roles/webapp/templates/.env.j2 rename to deploy/ansible/roles/galaxy_media_site/templates/.env.j2 diff --git a/deploy/ansible/roles/webapp/templates/webapp.service.j2 b/deploy/ansible/roles/galaxy_media_site/templates/gms.service.j2 similarity index 73% rename from deploy/ansible/roles/webapp/templates/webapp.service.j2 rename to deploy/ansible/roles/galaxy_media_site/templates/gms.service.j2 index 03dbb852..97947793 100644 --- a/deploy/ansible/roles/webapp/templates/webapp.service.j2 +++ b/deploy/ansible/roles/galaxy_media_site/templates/gms.service.j2 @@ -1,6 +1,6 @@ [Unit] Description=Gunicorn for Galaxy Media Site -Requires=webapp.socket +Requires=gms.socket After=network.target [Service] @@ -8,10 +8,10 @@ PIDFile=/run/gunicorn/pid User = www-data Group = www-data RuntimeDirectory=gunicorn -WorkingDirectory={{ web_root }} -Environment="PATH={{ venv_root }}/.venv/bin:$PATH" +WorkingDirectory={{ django_root }} +Environment="PATH={{ venv_root }}/bin:$PATH" ExecStart={{ venv_root }}/bin/gunicorn --pid /run/gunicorn/pid \ - --bind unix:/run/webapp.sock \ + --bind unix:/run/gms.sock \ -c {{ server_root }}/gunicorn.py webapp.wsgi ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID diff --git a/deploy/ansible/roles/webapp/templates/gunicorn.py.j2 b/deploy/ansible/roles/galaxy_media_site/templates/gunicorn.py.j2 similarity index 100% rename from deploy/ansible/roles/webapp/templates/gunicorn.py.j2 rename to deploy/ansible/roles/galaxy_media_site/templates/gunicorn.py.j2 diff --git a/deploy/ansible/roles/galaxy_media_site/templates/nginx.vhost.j2 b/deploy/ansible/roles/galaxy_media_site/templates/nginx.vhost.j2 new file mode 100644 index 00000000..2acdde20 --- /dev/null +++ b/deploy/ansible/roles/galaxy_media_site/templates/nginx.vhost.j2 @@ -0,0 +1,71 @@ +# Server config for {{ inventory_hostname }} (Galaxy media site) + +server { + # redirect www to non-www + server_name www.{{ inventory_hostname }}; + return 301 $scheme://{{ inventory_hostname }}$request_uri; +} + + +server { + + listen 80; + server_name {{ inventory_hostname }}; + access_log /var/log/nginx/gms.access.log; + error_log /var/log/nginx/gms.error.log; + + if ( $host !~* ^({{ inventory_hostname }})$ ) { + # Reject requests with incorrect host header + return 444; + } + + location = /biconcave { + return 404; + } + + location = /favicon.ico { + alias {{ django_root }}/webapp/static/favicon/favicon.ico; + } + + location /static { + root {{ django_root }}/webapp; + } + + location /media { + root {{ django_root }}/webapp; + } + + location / { + proxy_pass http://unix:/run/gms.sock; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_hide_header X-Frame-Options; + proxy_read_timeout 600; # seconds + client_max_body_size 1000m; + } + + {% if ssl_cert_exists %} + listen 443 ssl; # managed by Certbot + ssl_certificate /etc/letsencrypt/live/gms.neoformit.com/fullchain.pem; # managed by Certbot + ssl_certificate_key /etc/letsencrypt/live/gms.neoformit.com/privkey.pem; # managed by Certbot + include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot + {% endif %} + +} + +{% if ssl_cert_exists %} +server { + + if ($host = gms.neoformit.com) { + return 301 https://$host$request_uri; + } # managed by Certbot + + listen 80; + server_name gms.neoformit.com; + return 404; # managed by Certbot + +} +{% endif %} diff --git a/deploy/ansible/roles/webapp/templates/setup.sh.j2 b/deploy/ansible/roles/galaxy_media_site/templates/setup.sh.j2 similarity index 66% rename from deploy/ansible/roles/webapp/templates/setup.sh.j2 rename to deploy/ansible/roles/galaxy_media_site/templates/setup.sh.j2 index e361f906..eae35408 100644 --- a/deploy/ansible/roles/webapp/templates/setup.sh.j2 +++ b/deploy/ansible/roles/galaxy_media_site/templates/setup.sh.j2 @@ -1,23 +1,23 @@ -# Set up webapp and restart web services +# Set up gms and restart web services set -e source {{ venv_root }}/bin/activate -cd {{ project_root }}/webapp +cd {{ django_root }} # Set Django settings export DJANGO_SETTINGS_MODULE=webapp.settings.prod +# Collect static files for Nginx +python manage.py collectstatic --noinput + {% if not skip_database_migration %} # Migrate database python manage.py migrate {% endif %} -# Collect static files for Nginx -python manage.py collectstatic --noinput - # Restart services sudo systemctl daemon-reload -sudo systemctl enable webapp.service -sudo systemctl enable webapp.socket -sudo service webapp restart +sudo systemctl enable gms.service +sudo systemctl enable gms.socket +sudo service gms restart diff --git a/deploy/ansible/roles/webapp/templates/update.sh.j2 b/deploy/ansible/roles/galaxy_media_site/templates/update.sh.j2 similarity index 65% rename from deploy/ansible/roles/webapp/templates/update.sh.j2 rename to deploy/ansible/roles/galaxy_media_site/templates/update.sh.j2 index 8a2d8bb7..b0296552 100644 --- a/deploy/ansible/roles/webapp/templates/update.sh.j2 +++ b/deploy/ansible/roles/galaxy_media_site/templates/update.sh.j2 @@ -4,18 +4,18 @@ set -e -# Make sure this isn't being run as root -if [[ $EUID = 0 ]]; then - echo "Don't run this as root - ubuntu is fine!" +# Ensure run as root +if [[ $EUID != 0 ]]; then + echo "Must be run as root - use sudo" exit 0 fi # Source virtual environment and git pull -cd galaxy-content-site +cd {{ project_root }} source '{{ venv_root }}/bin/activate' git pull python -m pip install -r requirements.txt -cd webapp +cd {{ django_root }} # Collect any new static files for Nginx if neccessary python manage.py collectstatic --noinput @@ -24,11 +24,11 @@ python manage.py collectstatic --noinput python manage.py migrate # Update file ownership to allow www-data to write logs/media -sudo chown -R www-data:www-data webapp/logs -sudo chown -R www-data:www-data webapp/media +chown -R www-data:www-data webapp/logs +chown -R www-data:www-data webapp/media # Restart the GMS web service -sudo service webapp restart +service gms restart echo "" echo "~~~ Restarted Galaxy Media Site ~~~" diff --git a/deploy/ansible/roles/webapp/templates/nginx.vhost.j2 b/deploy/ansible/roles/webapp/templates/nginx.vhost.j2 deleted file mode 100644 index 7ee21fbc..00000000 --- a/deploy/ansible/roles/webapp/templates/nginx.vhost.j2 +++ /dev/null @@ -1,49 +0,0 @@ -# Server config for {{ inventory_hostname }} (Galaxy content site) - -server { - # redirect www to non-www - server_name www.{{ inventory_hostname }}; - return 301 $scheme://{{ inventory_hostname }}$request_uri; -} - - -server { - - listen 80; - server_name {{ inventory_hostname }}; - access_log /var/log/nginx/webapp.access.log; - error_log /var/log/nginx/webapp.error.log; - - if ( $host !~* ^({{ inventory_hostname }})$ ) { - # Reject requests with incorrect host header - return 444; - } - - location = /biconcave { - return 404; - } - - location = /favicon.ico { - alias {{ web_root }}/webapp/static/favicon/favicon.ico; - } - - location /static { - root {{ web_root }}/webapp; - } - - location /media { - root {{ web_root }}/webapp; - } - - location / { - proxy_pass http://unix:/run/webapp.sock; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_hide_header X-Frame-Options; - proxy_read_timeout 600; # seconds - client_max_body_size 1000m; - } - -} diff --git a/deploy/nginx.conf.tmpl b/deploy/nginx.conf.tmpl index ce9702f4..bfd29130 100644 --- a/deploy/nginx.conf.tmpl +++ b/deploy/nginx.conf.tmpl @@ -11,8 +11,8 @@ server { listen 80; server_name {{ HOSTNAME }}; - access_log /var/log/nginx/webapp.access.log; - error_log /var/log/nginx/webapp.error.log; + access_log /var/log/nginx/gms.access.log; + error_log /var/log/nginx/gms.error.log; if ( $host !~* ^({{ HOSTNAME }})$ ) { # Reject requests with incorrect host header @@ -24,19 +24,19 @@ server { } location = /favicon.ico { - alias /srv/sites/webapp/webapp/static/favicon/favicon.ico; + alias /srv/galaxy-media-site/webapp/gms/static/favicon/favicon.ico; } location /static { - root /srv/sites/webapp/webapp; + root /srv/galaxy-media-site/webapp/gms; } location /media { - root /srv/sites/webapp/webapp; + root /srv/galaxy-media-site/webapp/gms; } location / { - proxy_pass http://unix:/run/webapp.sock; + proxy_pass http://unix:/run/gms.sock; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; diff --git a/deploy/webapp.service.tmpl b/deploy/webapp.service.tmpl index 35c3dfee..9ca6a661 100644 --- a/deploy/webapp.service.tmpl +++ b/deploy/webapp.service.tmpl @@ -1,6 +1,6 @@ [Unit] Description=Gunicorn for Galaxy Media Site -Requires=webapp.socket +Requires=gms.socket After=network.target [Service] @@ -8,10 +8,10 @@ PIDFile=/run/gunicorn/pid User = ubuntu Group = www-data RuntimeDirectory=gunicorn -WorkingDirectory=/srv/sites/webapp +WorkingDirectory=/srv/galaxy-media-site/webapp Environment="PATH={{ PWD }}/.venv/bin:$PATH" ExecStart={{ PWD }}/.venv/bin/gunicorn --pid /run/gunicorn/pid \ - --bind unix:/run/webapp.sock \ + --bind unix:/run/gms.sock \ -c {{ PWD }}/gunicorn.py webapp.wsgi ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s TERM $MAINPID diff --git a/deploy/webapp.socket b/deploy/webapp.socket index 4eb3bbe1..094d1e5c 100644 --- a/deploy/webapp.socket +++ b/deploy/webapp.socket @@ -1,6 +1,6 @@ [Unit] Description=Galaxy content site socket [Socket] -ListenStream=/run/webapp.sock +ListenStream=/run/gms.sock [Install] WantedBy=sockets.target diff --git a/requirements.txt b/requirements.txt index 712ae716..0cd61d78 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,3 +20,4 @@ lxml Pillow requests==2.* requests_mock==1.* +sentry-sdk==2.* diff --git a/webapp/home/forms.py b/webapp/home/forms.py index d4c1985e..898231f9 100644 --- a/webapp/home/forms.py +++ b/webapp/home/forms.py @@ -174,8 +174,8 @@ class QuotaRequestForm(OtherFieldFormMixin, forms.Form): email = forms.EmailField() start_date = forms.DateField() duration_months = forms.IntegerField() - disk_tb = forms.IntegerField() - disk_tb_other = forms.IntegerField(required=False) + disk_tb = forms.FloatField() + disk_tb_other = forms.FloatField(required=False) description = forms.CharField() captcha = fields.ReCaptchaField() accepted_terms = forms.BooleanField() diff --git a/webapp/home/static/home/css/about.css b/webapp/home/static/home/css/about.css index 00b62540..64fd5728 100644 --- a/webapp/home/static/home/css/about.css +++ b/webapp/home/static/home/css/about.css @@ -11,45 +11,13 @@ hr { main { margin-bottom: 10rem; } - -.about-nav { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - margin-bottom: 3rem; - padding: 1rem; - border-bottom: 1px solid #eee; -} -.about-nav button { - display: inline-block; - color: #aaa; - font-size: 1rem; - text-decoration: none; - margin: .5rem; - padding: .25rem 1rem; - min-width: 150px; - text-align: center; - background: transparent; - border: none; - border-radius: .25rem; - transition-duration: .25s; - cursor: pointer; -} -.about-nav button.active { - color: #eee; - background: var(--color); - cursor: default; -} -.about-nav button:not(.active):hover { - color: #999; - background: rgba(50,50,50,0.1); -} section { - display: none; + margin-top: 6rem; + padding-bottom: 3rem; + border-bottom: 1px solid #aaa; } -section.show { - display: block; +section:last-child { + border-bottom: none; } .textbox { margin: 4rem; @@ -68,25 +36,11 @@ ol.nested ol ol > li { /* Responsive */ @media (max-width: 1200px) { - .about-nav { - padding: 1rem; - } - .about-nav button { - font-size: 0.85rem; - margin: .25rem; - padding: .25rem; - min-width: 125px; - } .textbox { margin: 2rem; } } @media (max-width: 880px) { - .about-nav button { - margin: .25rem; - padding: .25rem; - min-width: 0px; - } .textbox { margin: 1rem; } diff --git a/webapp/home/static/home/css/main.css b/webapp/home/static/home/css/main.css index fb6955e6..29bc3ac3 100644 --- a/webapp/home/static/home/css/main.css +++ b/webapp/home/static/home/css/main.css @@ -137,6 +137,9 @@ section { margin-left: 0; margin-right: 0; } +.narrow { + max-width: 600px; +} .container-centered { /* For content centered on full @@ -149,6 +152,10 @@ section { width: 100%; height: 85vh; } +.my-10 { + margin-top: 6rem; + margin-bottom: 6rem; +} /* Forms */ input.invalid, diff --git a/webapp/home/static/home/css/request-form.css b/webapp/home/static/home/css/request-form.css index 459b9014..ace9d5ae 100644 --- a/webapp/home/static/home/css/request-form.css +++ b/webapp/home/static/home/css/request-form.css @@ -27,7 +27,7 @@ ul.errorlist { border: 1px solid var(--error); border-radius: .5rem; } -[class^="col"] { +.row [class^="col"] { padding-bottom: 1rem; } .blockquote { diff --git a/webapp/home/static/home/css/requests.css b/webapp/home/static/home/css/requests.css index c6a5d2c0..1651aa85 100644 --- a/webapp/home/static/home/css/requests.css +++ b/webapp/home/static/home/css/requests.css @@ -59,4 +59,17 @@ span.material-icons { font-size: 0.8rem; padding: 0; } + .request-menu-cards .ga-btn { + min-width: 100px; + } } +@media (max-width: 575px) { + .request-menu-cards .card { + padding: 2rem 1rem; + margin: .5rem auto; + max-width: 300px; + } + .request-menu-cards .card-body { + font-size: 1rem; + } +} \ No newline at end of file diff --git a/webapp/home/templates/embed-snippet.html b/webapp/home/templates/embed-snippet.html index 78707c18..4f719b2b 100644 --- a/webapp/home/templates/embed-snippet.html +++ b/webapp/home/templates/embed-snippet.html @@ -10,3 +10,12 @@ {% block content %} {% include snippet_path %} {% endblock %} + +{% block script %} + +{% endblock %} diff --git a/webapp/home/templates/home/about.html b/webapp/home/templates/home/about.html index 059f8554..13b99870 100644 --- a/webapp/home/templates/home/about.html +++ b/webapp/home/templates/home/about.html @@ -10,35 +10,54 @@ {% block content %} -
- - - - - - - - - - - -
-
-
+ +

About Galaxy Australia

+ +

+ Galaxy Australia provides researchers with free access to a high-performance computing network through a simple web interface. +

+ +

+ Galaxy Australia maintains tools, workflows and reference datasets as requested by the Australian research community, making the platform the ideal place for Australian researchers to perform their analyses. If we do not currently support your specific application or species then we will endeavour to make it available. + Please just ask! +

+ +

+ Galaxy Australia is part of the usegalaxy.* initiative. Visit the + Galaxy Project Community Hub + for more information. +

+ + + +
{% include 'home/snippets/about/about.html' %}
@@ -67,85 +86,8 @@ {% block script %} - - - {% endblock %} {% block onload %} - -// Prevent default hash scroll -if (location.hash) { - console.log("Set timeout to intercept hash scroll"); - setTimeout(function() { - window.scrollTo(0, 0); - }, 10); -} - -window.location.hash && setTimeout(function() { - scrollToId(window.location.hash.slice(1)); -}, 100); - -$('a').click( e => { - if ( - e.target.href.startsWith(window.location.origin) - && e.target.href.includes('#')) { - // It's an internal link - e.preventDefault(); - scrollToId(e.target.href.split('#')[1]); - } -}) - {% endblock %} diff --git a/webapp/home/templates/home/header-export.html b/webapp/home/templates/home/header-export.html index cc49fd95..f4730bd4 100644 --- a/webapp/home/templates/home/header-export.html +++ b/webapp/home/templates/home/header-export.html @@ -22,7 +22,7 @@ - + {% block content %} {% endblock %} diff --git a/webapp/home/templates/home/header.html b/webapp/home/templates/home/header.html index eaf720fc..81def67e 100644 --- a/webapp/home/templates/home/header.html +++ b/webapp/home/templates/home/header.html @@ -200,18 +200,28 @@ // Remove links to usegalaxy.org.au if in iframe // ...otherwise risk having galaxy-in-galaxy which is very weird! + // If GMS (local) URL then do nothing + // If parent root URL then remove href + // Else must be: + // - non-root parent URL + // - OR external URL + // -> set target="_blank" (opens in new tab) + const urlParams = new URLSearchParams(window.location.search); + const parentHostname = urlParams.get('hostname') || 'usegalaxy.org.au'; if ( inIframe() ) { $('a').each( (i, el) => { if ( el.href - && el.href.includes('https://{{ HOSTNAME }}') + && !el.href.startsWith('https://{{ HOSTNAME }}') && !isLabPage() ) { - if (el.href.replace(/\/$/, "") === 'https://{{ HOSTNAME }}') { - console.log(`Remove href from anchor: ${el.href}`); + if (el.href.replace(/\/$/, "") === `https://${parentHostname}`) { + // It's a link to the parent site root URL + // console.log(`Remove href from anchor: ${el.href}`); $(el).removeAttr("href"); } else { - console.log(`Set target="_blank" on anchor: ${el.href}`); + // It's a link to the parent site with a path, or an external site + // console.log(`Set target="_blank" on anchor: ${el.href}`); $(el).attr("target", "_blank"); } } diff --git a/webapp/home/templates/home/requests/access/index.html b/webapp/home/templates/home/requests/access/index.html index 113a7f1c..7fcc2889 100644 --- a/webapp/home/templates/home/requests/access/index.html +++ b/webapp/home/templates/home/requests/access/index.html @@ -81,6 +81,20 @@

Request access to specialist tools

+ +
+
+

+ Analyse data-independent acquisition (DIA) proteomics data with DiaNN +

+
+ + +
diff --git a/webapp/home/templates/home/requests/access/snippets/agree-terms-modal.html b/webapp/home/templates/home/requests/access/snippets/agree-terms-modal.html index 9439aad1..7435d57b 100644 --- a/webapp/home/templates/home/requests/access/snippets/agree-terms-modal.html +++ b/webapp/home/templates/home/requests/access/snippets/agree-terms-modal.html @@ -76,6 +76,8 @@ .css('padding', '1rem')); {% endif %} + const isMac = () => navigator.platform.toUpperCase().indexOf('MAC') >= 0; + function agreeTermsAction(el) { enableTermsInput(); $('#agreeTermsInput').attr('checked', true); @@ -92,16 +94,20 @@ tooltip.disable(); } + function setEventHandler() { const termsContainer = $('#termsModal iframe').contents().find('body'); if (!termsContainer.length) { return setTimeout(setEventHandler, 100); } + if (isMac()) { + return enableAgreeTermsButton(); + } $('#termsModal iframe').contents().on('scroll', (event) => { const scrollFromEnd = $(termsContainer)[0].scrollHeight - $('#termsModal iframe').contents().scrollTop() - $('#termsModal iframe').height(); - if (scrollFromEnd < 50) enableAgreeTermsButton(); + scrollFromEnd < 50 && enableAgreeTermsButton(); }); termsContainer.css('margin', 'auto'); } diff --git a/webapp/home/templates/home/requests/menu.html b/webapp/home/templates/home/requests/menu.html index 708ed181..6a65700a 100644 --- a/webapp/home/templates/home/requests/menu.html +++ b/webapp/home/templates/home/requests/menu.html @@ -70,7 +70,8 @@

save

key

- Request access to specialised tools AlphaFold 2, FGENESH++ and Cell Ranger + Request access to specialised tools AlphaFold 2, FGENESH++, + Cell Ranger and more...

diff --git a/webapp/home/templates/home/requests/quota.html b/webapp/home/templates/home/requests/quota.html index 78ccb13a..9e6217b3 100644 --- a/webapp/home/templates/home/requests/quota.html +++ b/webapp/home/templates/home/requests/quota.html @@ -40,15 +40,15 @@

Galaxy Australia Quota Increase Application

{% csrf_token %} -
-
+
+
{{ form.name.errors }}
-
+
Galaxy Australia Quota Increase Application
-
-
+
+
@@ -87,28 +87,36 @@

Galaxy Australia Quota Increase Application

{{ form.start_date.errors }}
-
+
-
- + -
- - months - -
+ +
+
+ + +
+
+ +
+ {{ form.duration_months.errors }}
-
-
+
+

What is the total storage space you require?

@@ -116,14 +124,21 @@

Galaxy Australia Quota Increase Application

{{ form.disk_tb.errors }}
- + +
+ +
+
- @@ -148,20 +163,13 @@

Galaxy Australia Quota Increase Application

- -
- - -
{{ form.description.errors }}
- Please briefly justify your need for additional data storage. - Describe your data, file types and why they are required for your research. + Please briefly justify your need for additional data storage by + describing your data and intended analysis.
-
+

Agreement on the use of the Galaxy Australia Server

diff --git a/webapp/home/templates/home/snippets/about/about.html b/webapp/home/templates/home/snippets/about/about.html index a849553c..36e2fd27 100644 --- a/webapp/home/templates/home/snippets/about/about.html +++ b/webapp/home/templates/home/snippets/about/about.html @@ -1,24 +1,7 @@ {% load static %} -

About Galaxy Australia

- -

- Galaxy Australia provides researchers with free access to a high-performance computing network through a simple web interface. -

- -

- Galaxy Australia maintains tools, workflows and reference datasets as requested by the Australian research community, making the platform the ideal place for Australian researchers to perform their analyses. If we do not currently support your specific application or species then we will endeavour to make it available. - Please just ask! -

- -

- Galaxy Australia is part of the usegalaxy.* initiative. Visit the - Galaxy Project Community Hub - for more information. -


-

Galaxy Australia Acknowledgment Statement

@@ -40,107 +23,111 @@

-
-

- Operational Partners -

-

-Australian BioCommons (hosted by - the University of Melbourne) - operates Galaxy Australia in collaboration with - QCIF, - The University of Melbourne - and - AARNet.
- This service forms part of the national Australian BioCommons infrastructure. -

-