Nouse was based on "bCMS" originally, a custom built content management system. There's probably going to always be some debate about whether this was the best idea for Nouse, but it has enabled us to do some really great custom stuff over the years, and overcome crippling performance issues on Wordpress.
Please see LOCAL.md
for instructions.
Firstly, an apology. This repo was, in its early life, a 3-year labour of love of over 580 commits just trying to keep up with Nouse as the society grew and its needs developed. There are no tests or migrations and documentation is limited. Code quality and style varies as the project grew alongside its creators skill set. No linting is provided or used.
For performance reasons, the site does not use a router, and instead leaves routing to Apache. Caddy sits in front of appache to termiate SSL and do some reverse proxying. The project is structured around three directories within /html:
admin - The "backend" edit dashboard common - (not publicly accessible) Classes, Functions & Templates shared by both other directories frontend - "Public Site" nouse.co.uk
To improve user performance & error handling the backend site is not based around a conventional laravel-esque form structure for user interaction. Instead, most data from the database is returned to the user through a normal dynamically loaded page, generating html from a twig template.
When a user interacts with the page, such as pressing a button, this triggers a JQuery function (all defined in that pages' twig template) which makes an "api call" to a php script within the admin/api/
folder and executes the change (such as an insert/delete/update). Once this completes successfully two things can happen. The first, a legacy behaviour, is that the page reloads to reflect the changes in the page itself. The second option is that the page calls a function to update what's displayed, without needing a page re-load. There are quite a few endpoints in admin/api
that provide access to retrieving data as well, as this is how the mobile app downloads its data which it then displays.
With hindsight this was not a great way to do this.
The whole stack runs off one docker-compose file which makes this all a lot simpler!
- Make sure you're the root user
sudo su
thencd /root/
apt update && apt install docker.io docker-compose
systemctl enable docker
to ensure docker boots on startup- Clone the repo
git clone [email protected]:yorknouse/website.git
cd website
to get into it- Download the Cloudflare Origin Certificate - place the certificate (
.crt
file) in thessl
directory, with thessl.key
file - Create
nouseprod.env
based on the example file, and fill out the details (do this withnano nouseprod.env
) - Run
docker-compose up -d
to get the site running
Some pages in the website are statically built, nominally the home page. To rebuild them, the host vm needs a webhook that can be triggered from the admin panel and causes the docker images to be rebuilt.
Setting up:
sudo apt-get install webhook
In the /root
directory, create a rebuild-webhook.json
file with the following content:
[
{
"id": "rebuild-webhook",
"execute-command": "/root/rebuild.sh",
"command-working-directory": "/root/website"
}
]
Still in the /root
folder, create the rebuild.sh
file with the following content:
#!/bin/sh
git pull && docker-compose -f docker-compose.yml build --no-cache nouse && docker-compose -f docker-compose.yml up -d
And make the script executable:
chmod +x /root/rebuild.sh
Now we need a service to start webhook on boot. Create the /etc/systemd/system/rebuild.service
file with the following content:
[Unit]
Description=Webhook Rebuild Service
After=network.target
[Service]
ExecStart=/usr/bin/webhook -hooks=/root/rebuild-webhook.json -hotreload=false -port=9000 -secure=false -verbose=true -nopanic
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
Finally, reload the systemd daemon, disable the default webhook service and enable ours:
systemctl daemon-reload && systemctl disable webhook.service && systemctl enable rebuild.service
Watchtower does the updating for you anytime you push a new tag (which triggers a docker build) but if you update the docker compose file or the config you'll need to run git pull && docker-compose up -d
(in the Nouse directory)
You need to setup the CORS on the bucket to allow uploads from any host, and downloads from any host
First download and authenticate the AWS Cli (using your Backblaze credentials), then download the cors.json file from this repo and run:
aws s3api put-bucket-cors --bucket=nousePublicBackendUploads --endpoint-url=https://s3.eu-central-003.backblazeb2.com --cors-configuration=file://cors.json
To transfer a MySQL dump file (named nouseBackup.sql
) run:
cat nouseBackup.sql | docker exec -i db /usr/bin/mysql -u root --password=rootPass nouse
mysql-backup
runs a backup every day at about 2:30am and pops it in our S3 bucket. That's all automatic, but you do need to set up a lifecycle rule for the spaces/S3 bucket. This is so the backups are deleted after 40 days and we don't get bancrupted by them.
- Set the lifecycle policy for the bucket using the
lifecycle.xml
file
phpmyadmin is accessible at http://yusunouse01.york.ac.uk/tools/phpmyadmin, with login = nouseAdmin and password = [nouseAdminPassword set in nouseprod.env]
netdata is accessible at http://yusunouse01.york.ac.uk/tools/netdata, with login = nouseAdmin and password = [nouseAdminPassword set in nouseprod.env]
Grafana (stats.nouse.co.uk) runs as an instance inside the MySQL server. It has full root access to the database due to Docker limitations so as such no users have edit permissions. Instead, set up your queries and graphs in the text files under "
docker/grafana/dashboards`. You can also generate these locally by running grafana and using the UI to export JSON files.
Grafana security is managed by an oauth hook from the main admin site.
Copyright (C) 2018-2021 Nouse, University of York Students Union and its contributors
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.