diff --git a/.gitignore b/.gitignore
index e1dba2e..67588a1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,9 @@
/build
-*/uploads
+*/mediafiles
+*/staticfiles
__pycache__
*.pyc
.venv
+.env*
*.sqlite3
diff --git a/README.md b/README.md
index d7112f5..cc8fb86 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Web backend for hosting a wedding website.
-## Run development server:
+# Run Local server:
```sh
source .venv/bin/activate
@@ -10,10 +10,49 @@ cd wedding_site
python manage.py runserver
```
-## Do Migrations
+# Do Migrations
```sh
cd wedding_site
python manage.py makemigrations primary
python manage.py migrate
-```
\ No newline at end of file
+```
+
+# Run Dev Server in container
+
+```sh
+podman-compose -f compose.yaml up -d --build
+```
+
+Bring it down with:
+
+```sh
+podman-compose down -v
+```
+
+# Run Prod Server
+
+```sh
+podman-compose -f compose.prod.yaml up -d --build
+```
+
+Sync static files:
+
+```sh
+podman-compose -f compose.prod.yaml exec web python manage.py collectstatic --no-input --clear
+```
+
+Check cert
+
+```sh
+podman-compose -f compose.prod.yaml exec acme-companion /app/cert_status
+```
+
+Force renew cert:
+
+```sh
+podman-compose -f compose.prod.yaml exec acme-companion /app/force_renew
+```
+
+
+
diff --git a/compose.prod.yaml b/compose.prod.yaml
new file mode 100644
index 0000000..a60429c
--- /dev/null
+++ b/compose.prod.yaml
@@ -0,0 +1,52 @@
+version: '3.8'
+
+services:
+ web:
+ build: ./wedding_site
+ command: gunicorn wedding_site.wsgi:application --bind 0.0.0.0:8000
+ volumes:
+ - ./wedding_site/:/usr/src/app/
+ - static_volume:/staticfiles
+ - media_volume:/mediafiles
+ expose:
+ - 8000
+ env_file:
+ - ./.env.prod
+
+ nginx-proxy:
+ container_name: nginx-proxy
+ build: ./nginx
+ restart: always
+ ports:
+ - 443:443
+ - 80:80
+ volumes:
+ - static_volume:/staticfiles
+ - media_volume:/mediafiles
+ - certs:/etc/nginx/certs
+ - html:/usr/share/nginx/html
+ - vhost:/etc/nginx/vhost.d
+ - /var/run/docker.sock:/tmp/docker.sock:ro
+ depends_on:
+ - web
+
+ acme-companion:
+ image: docker.io/nginxproxy/acme-companion
+ env_file:
+ - ./.env.prod.proxy-companion
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock:ro
+ - certs:/etc/nginx/certs
+ - html:/usr/share/nginx/html
+ - vhost:/etc/nginx/vhost.d
+ - acme:/etc/acme.sh
+ depends_on:
+ - nginx-proxy
+
+volumes:
+ static_volume:
+ media_volume:
+ certs:
+ html:
+ vhost:
+ acme:
\ No newline at end of file
diff --git a/compose.staging.yaml b/compose.staging.yaml
new file mode 100644
index 0000000..5d151a9
--- /dev/null
+++ b/compose.staging.yaml
@@ -0,0 +1,52 @@
+version: '3.8'
+
+services:
+ web:
+ build: ./wedding_site
+ command: gunicorn wedding_site.wsgi:application --bind 0.0.0.0:8000
+ volumes:
+ - ./wedding_site/:/usr/src/app/
+ - static_volume:/staticfiles
+ - media_volume:/mediafiles
+ expose:
+ - 8000
+ env_file:
+ - ./.env.staging
+
+ nginx-proxy:
+ container_name: nginx-proxy
+ build: ./nginx
+ restart: always
+ ports:
+ - 443:443
+ - 80:80
+ volumes:
+ - static_volume:/staticfiles
+ - media_volume:/mediafiles
+ - certs:/etc/nginx/certs
+ - html:/usr/share/nginx/html
+ - vhost:/etc/nginx/vhost.d
+ - /var/run/docker.sock:/tmp/docker.sock:ro
+ depends_on:
+ - web
+
+ acme-companion:
+ image: docker.io/nginxproxy/acme-companion
+ env_file:
+ - ./.env.staging.proxy-companion
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock:ro
+ - certs:/etc/nginx/certs
+ - html:/usr/share/nginx/html
+ - vhost:/etc/nginx/vhost.d
+ - acme:/etc/acme.sh
+ depends_on:
+ - nginx-proxy
+
+volumes:
+ static_volume:
+ media_volume:
+ certs:
+ html:
+ vhost:
+ acme:
\ No newline at end of file
diff --git a/compose.yaml b/compose.yaml
new file mode 100644
index 0000000..ddaa801
--- /dev/null
+++ b/compose.yaml
@@ -0,0 +1,12 @@
+version: '3.8'
+
+services:
+ web:
+ build: ./wedding_site
+ command: python manage.py runserver 0.0.0.0:8000
+ volumes:
+ - ./wedding_site/:/usr/src/app/
+ ports:
+ - 8000:8000
+ env_file:
+ - ./.env.dev
\ No newline at end of file
diff --git a/infra/install_arch_deps.sh b/infra/install_arch_deps.sh
new file mode 100644
index 0000000..8937870
--- /dev/null
+++ b/infra/install_arch_deps.sh
@@ -0,0 +1 @@
+pacman -Sy podman aardvark-dns
\ No newline at end of file
diff --git a/nginx/Dockerfile b/nginx/Dockerfile
new file mode 100644
index 0000000..98aa030
--- /dev/null
+++ b/nginx/Dockerfile
@@ -0,0 +1,4 @@
+FROM docker.io/nginxproxy/nginx-proxy
+
+COPY vhost.d/default /etc/nginx/vhost.d/default
+COPY custom.conf /etc/nginx/conf.d/custom.conf
\ No newline at end of file
diff --git a/nginx/custom.conf b/nginx/custom.conf
new file mode 100644
index 0000000..e9a5e8e
--- /dev/null
+++ b/nginx/custom.conf
@@ -0,0 +1 @@
+client_max_body_size 100M;
\ No newline at end of file
diff --git a/nginx/vhost.d/default b/nginx/vhost.d/default
new file mode 100644
index 0000000..bd8fd4d
--- /dev/null
+++ b/nginx/vhost.d/default
@@ -0,0 +1,9 @@
+location /static/ {
+ alias /staticfiles/;
+ add_header Access-Control-Allow-Origin *;
+}
+
+location /media/ {
+ alias /mediafiles/;
+ add_header Access-Control-Allow-Origin *;
+}
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 2e2e3ab..e7584bd 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1 @@
-django
-markdown
-pillow
-beautifulsoup4
+podman-compose
\ No newline at end of file
diff --git a/wedding_site/Dockerfile b/wedding_site/Dockerfile
new file mode 100644
index 0000000..0b84079
--- /dev/null
+++ b/wedding_site/Dockerfile
@@ -0,0 +1,19 @@
+# pull official base image
+FROM python:3.11.4-slim-buster
+
+# set environment variables
+ENV PYTHONDONTWRITEBYTECODE 1
+ENV PYTHONUNBUFFERED 1
+
+# install dependencies
+RUN pip install --upgrade pip
+COPY ./requirements.txt .
+RUN pip install -r requirements.txt
+
+RUN mkdir staticfiles
+RUN mkdir mediafiles
+
+ADD ./mediafiles /mediafiles
+
+# copy project
+COPY . .
\ No newline at end of file
diff --git a/wedding_site/primary/migrations/0010_page_prority.py b/wedding_site/primary/migrations/0010_page_prority.py
new file mode 100644
index 0000000..01223ed
--- /dev/null
+++ b/wedding_site/primary/migrations/0010_page_prority.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.2 on 2024-02-18 09:58
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('primary', '0009_page_pretty_name'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='page',
+ name='prority',
+ field=models.IntegerField(default=0),
+ ),
+ ]
diff --git a/wedding_site/primary/migrations/0011_rename_prority_page_priority.py b/wedding_site/primary/migrations/0011_rename_prority_page_priority.py
new file mode 100644
index 0000000..42ac5dd
--- /dev/null
+++ b/wedding_site/primary/migrations/0011_rename_prority_page_priority.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.2 on 2024-02-18 10:02
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('primary', '0010_page_prority'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='page',
+ old_name='prority',
+ new_name='priority',
+ ),
+ ]
diff --git a/wedding_site/primary/models.py b/wedding_site/primary/models.py
index a73c009..ac7603e 100644
--- a/wedding_site/primary/models.py
+++ b/wedding_site/primary/models.py
@@ -18,6 +18,7 @@ class Page(models.Model):
pretty_name = models.CharField(max_length=200, default="")
published = models.BooleanField(default=False)
navigable = models.BooleanField(default=False)
+ priority = models.IntegerField(default=0)
def __str__(self):
return self.name
diff --git a/wedding_site/primary/static/primary/favicon.ico b/wedding_site/primary/static/primary/favicon.ico
new file mode 100755
index 0000000..115ea84
Binary files /dev/null and b/wedding_site/primary/static/primary/favicon.ico differ
diff --git a/wedding_site/primary/static/primary/style.css b/wedding_site/primary/static/primary/style.css
index 8384158..b1383e3 100755
--- a/wedding_site/primary/static/primary/style.css
+++ b/wedding_site/primary/static/primary/style.css
@@ -33,9 +33,9 @@ body {
img {
margin:0 auto;
- width: 100%;
display: flex;
justify-content: center;
+ max-width:100%;
max-height:300px;
border-radius: 8px;
box-shadow: 0 4px 8px 0;
@@ -107,6 +107,10 @@ ul {
list-style-position: inside;
}
+ul li {
+ padding: 5px 0px;
+}
+
.login-input{
margin-top: 30px;
text-align: center;
@@ -143,7 +147,7 @@ input[type=submit] {
margin-top: 30px;
text-align: center;
font-size: 20px;
- width: 50%;
+ width: 75%;
margin:0 auto;
font-family: GlacialIndifference;
}
diff --git a/wedding_site/primary/templates/header.html b/wedding_site/primary/templates/header.html
index 6574036..32bb550 100644
--- a/wedding_site/primary/templates/header.html
+++ b/wedding_site/primary/templates/header.html
@@ -3,4 +3,5 @@
content="width=device-width, initial-scale=1">
{% load static %}
+
\ No newline at end of file
diff --git a/wedding_site/primary/urls.py b/wedding_site/primary/urls.py
index bb59882..2fe363b 100644
--- a/wedding_site/primary/urls.py
+++ b/wedding_site/primary/urls.py
@@ -7,6 +7,7 @@ urlpatterns = [
path("", views.index, name="index"),
path('login', views.login_view, name="login"),
path("home", views.home, name="home"),
+ path("afters", views.afters, name="afters"),
path("schedule", views.schedule, name="schedule"),
path("thingstodo", views.things_to_do, name="thingstodo"),
path("travel", views.travel, name="travel"),
diff --git a/wedding_site/primary/views.py b/wedding_site/primary/views.py
index f9295ff..30ffb5d 100644
--- a/wedding_site/primary/views.py
+++ b/wedding_site/primary/views.py
@@ -6,6 +6,8 @@ from django.template import Context
from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
+from django.views.defaults import page_not_found
+
import markdown
from bs4 import BeautifulSoup
@@ -24,6 +26,17 @@ _TEMPLATE = """