diff --git a/.dockerignore b/.dockerignore index 0da5edc..b0e33dc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,5 @@ *.pyc *.pyo /.env -/data -/static_collected +/docker /node_modules diff --git a/.env-db b/.env-db.example similarity index 100% rename from .env-db rename to .env-db.example diff --git a/.env-local b/.env-local index a6d4e75..e570215 100644 --- a/.env-local +++ b/.env-local @@ -1,2 +1,2 @@ -DATABASE_URL=postgres://postgres@postgres:5432/db -DEFAULT_HAYSTACK_URL=es+https://tcjf1ngoog:qj70l67kk2@tagesschule-elementa-8329801232.eu-west-1.bonsaisearch.net/test-* \ No newline at end of file +DATABASE_URL=postgres://django@MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX:5432/db +DEFAULT_HAYSTACK_URL=es+https://tcjf1ngoog:qj70l67kk2@tagesschule-elementa-8329801232.eu-west-1.bonsaisearch.net/test-* diff --git a/.env b/.env.example similarity index 70% rename from .env rename to .env.example index 394df2f..4ae2841 100644 --- a/.env +++ b/.env.example @@ -1,5 +1,9 @@ SECRET_KEY=TEST---asdg4hr63453452542h4sdf25g42s3df54hj38rd4sg3f2d54h3sd5f4g53 -DEBUG=False +DEBUG=True SENTRY_DSN=https://460e310d034c49a794941e087c4fcc6e@sentry.io/1196285 DEFAULT_HAYSTACK_URL=es+https://tcjf1ngoog:qj70l67kk2@tagesschule-elementa-8329801232.eu-west-1.bonsaisearch.net/index-* -DATABASE_URL=postgres://django:MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX@postgres:5432/db \ No newline at end of file +DATABASE_URL=postgres://django:MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX@postgres:5432/db +HTTP_PORT=8009 +HTTPS_PORT=4047 +POSTGRES_PASSWORD=MuzQzD6yLyaksfw9f6NUDLsK6Tp7gD7f8uX +POSTGRES_USER=django diff --git a/.gitignore b/.gitignore index 7c4695e..412e319 100644 --- a/.gitignore +++ b/.gitignore @@ -15,9 +15,8 @@ Thumbs.db # Aldryn .aldryn -/data /data.tar.gz -/static_collected +/docker/static_collected /node_modules # /static/css/ @@ -27,4 +26,9 @@ Thumbs.db /static/animation/ /.idea /requirements.txt -/conf/certbot/ \ No newline at end of file +/docker/conf/certbot/ +/docker/pgdata/** +/docker/data +.env-nginx +.env-db +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..edac68d --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Tagesschule elementa + + +## Docker + +1. Copy environment files `.env*.example` to `.env*` and make the configuration changes. +Configure database user and ports for docker. + - HTTP_PORT=8009 [.env] + - HTTPS_PORT=4047 [.env] + +2. Main app has several mountpoints / volumes. Point them into the appropriate location on +your filesystem + - ./docker/static_collected + - ./docker/data/media + - ./docker/data + +3. To start + + docker-compose up + +4. Restore DB + + docker exec -i tagesschule_db_1 pg_restore -U django --no-owner -d db < 41ebf901-4607-4653-9b00-54a42d877b38.dump + +3. Migrate + + docker-compose exec web manage.py migrate + +5. diff --git a/conf/nginx/app.conf b/conf/nginx/app.conf deleted file mode 100644 index c8ba7da..0000000 --- a/conf/nginx/app.conf +++ /dev/null @@ -1,61 +0,0 @@ -upstream gunicorn { - server web:80; -} - - -server { - listen 80; - server_name tagesschule.mprofiag.ch; - server_tokens off; - - location /.well-known/acme-challenge/ { - root /var/www/certbot; - } - - location / { - return 301 https://$host$request_uri; - } -} - -server { - listen 443 ssl; - server_name tagesschule.mprofiag.ch; - server_tokens off; - sendfile on; - - ssl_certificate /etc/letsencrypt/live/tagesschule.mprofiag.ch/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/tagesschule.mprofiag.ch/privkey.pem; - include /etc/letsencrypt/options-ssl-nginx.conf; - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - - add_header X-Frame-Options ""; - - gzip on; - gzip_http_version 1.1; - gzip_disable "MSIE [1-6]\."; - gzip_min_length 256; - gzip_vary on; - gzip_proxied expired no-cache no-store private auth; - gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; - gzip_comp_level 9; - - location /static/ { - sendfile on; - alias /app/static_collected/; - } - - location /media/ { - sendfile on; - alias /app/data/media/; - } - - location / { - proxy_hide_header X-Frame-Options; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $host; - proxy_redirect off; - proxy_pass http://gunicorn; - } -} - diff --git a/docker-compose.yml b/docker-compose.yml index a14bc52..b42ef07 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,45 +1,20 @@ version: '3' services: - nginx: - image: nginx:1.16-alpine - restart: unless-stopped - volumes: - - ./conf/nginx:/etc/nginx/conf.d - - ./conf/certbot/conf:/etc/letsencrypt - - ./conf/certbot/www:/var/www/certbot - - ./static_collected:/app/static_collected - - ./data/media:/app/data/media - ports: - - "80:80" - - "443:443" - command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'" - depends_on: - - web - networks: - - nginx_network - - certbot: - image: certbot/certbot - restart: unless-stopped - volumes: - - ./conf/certbot/conf:/etc/letsencrypt - - ./conf/certbot/www:/var/www/certbot - entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'" - web: build: "." links: - "db:postgres" volumes: - ".:/app:rw" - - "./data:/data:rw" - - ./static_collected:/app/static_collected - - ./data/media:/app/data/media + - "./docker/data:/data:rw" + - ./docker/static_collected:/app/static_collected + - ./docker/data/media:/app/data/media networks: - - nginx_network - db_network command: "/bin/sh -c '/app/wait-for-postgres.sh postgres /app/run.sh'" + ports: + - ${HTTP_PORT}:80 env_file: - ./.env db: @@ -47,13 +22,10 @@ services: env_file: - ./.env-db volumes: - - ".:/app:rw" - - "./pgdata:/var/lib/postgresql/data:rw" + - "./docker/pgdata:/var/lib/postgresql/data:rw" networks: - db_network networks: - nginx_network: - driver: bridge db_network: - driver: bridge \ No newline at end of file + driver: bridge diff --git a/docker/pgdata/.gitkeep b/docker/pgdata/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/requirements.in b/requirements.in index d102675..448d33d 100644 --- a/requirements.in +++ b/requirements.in @@ -20,4 +20,5 @@ mailchimp3==2.1.0 django-image-cropping==1.2.0 django-anymail[mailgun]==1.4 django-admin-view-permission==1.9 -gunicorn==19.9.0 \ No newline at end of file +gunicorn==19.9.0 +django-storages<1.9 # https://stackoverflow.com/questions/60297619/divio-importerror-cannot-import-name-s3boto diff --git a/src/portal/migrations/0005_auto_20200325_1611.py b/src/portal/migrations/0005_auto_20200325_1611.py new file mode 100644 index 0000000..fdb7e7c --- /dev/null +++ b/src/portal/migrations/0005_auto_20200325_1611.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.21 on 2020-03-25 16:11 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import parler.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('portal', '0004_auto_20180718_1754'), + ] + + operations = [ + migrations.AlterModelOptions( + name='announcement', + options={'ordering': ['-updated'], 'verbose_name': 'Neuigkeit', 'verbose_name_plural': 'Aktuell'}, + ), + migrations.AlterField( + model_name='announcementtranslation', + name='master', + field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.Announcement'), + ), + migrations.AlterField( + model_name='downloadfiletranslation', + name='master', + field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.DownloadFile'), + ), + migrations.AlterField( + model_name='downloadsectiontranslation', + name='master', + field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.DownloadSection'), + ), + migrations.AlterField( + model_name='informationsectiontranslation', + name='master', + field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.InformationSection'), + ), + migrations.AlterField( + model_name='informationtranslation', + name='master', + field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='portal.Information'), + ), + ] diff --git a/src/project/migrations/0010_auto_20200325_1611.py b/src/project/migrations/0010_auto_20200325_1611.py new file mode 100644 index 0000000..670e3fb --- /dev/null +++ b/src/project/migrations/0010_auto_20200325_1611.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.21 on 2020-03-25 16:11 +from __future__ import unicode_literals + +from django.db import migrations +import django.db.models.deletion +import parler.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('project', '0009_auto_20190214_1250'), + ] + + operations = [ + migrations.AlterField( + model_name='notificationtranslation', + name='master', + field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='project.Notification'), + ), + migrations.AlterField( + model_name='slideritemqualificationtranslation', + name='master', + field=parler.fields.TranslationsForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='translations', to='project.SliderItemQualification'), + ), + ] diff --git a/wait-for-postgres.sh b/wait-for-postgres.sh index c944446..1838573 100755 --- a/wait-for-postgres.sh +++ b/wait-for-postgres.sh @@ -7,10 +7,10 @@ host="$1" shift cmd="$@" -until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "postgres" -c '\q'; do +until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c '\q'; do >&2 echo "Postgres is unavailable - sleeping" sleep 1 done >&2 echo "Postgres is up - executing command" -exec $cmd \ No newline at end of file +exec $cmd