In a few minutes you can have your own HTTPS, responsive site hosting text, photos, and videos.
Follow along with the instructions below to get started.
Install Python3, ImageMagick, and FFmpeg locally:
[local]$ brew install python
[local]$ brew install imagemagick
[local]$ brew install ffmpeg
- Get a domain name (e.g. google.com), which we'll call
{host}
- I like namecheap
- Note that
{host}
is not prefixed withwww.
- Get an Ubuntu 18.04 server with ssh access to
root
- You can set one up through DigitalOcean
- Configure DNS to point the domain to the server
- You can follow these instructions
You can verify that your domain points to your server's IP with:
[local]$ nslookup {host}
Set up your server with the following commands, substituting your domain for
{host}
.
1. Clone the repo
[local]$ git clone [email protected]:newmediacollective/Sites.git
[local]$ cd Sites
2. Configure your local environment
If you already manage Python virtual environments, feel free to set up a virtual environment how you normally do, then run:
[local]$ pip install -r requirements.txt
Otherwise, you can set up a virtual environment with:
[local]$ source scripts/setup_local.sh
- This will create a virtual environment in
app/.env
- All
python
commands should be run with your virtual environment activated - Activate with
source app/.env/bin/activate
- Deactivate with
deactivate
- All
3. Configure your remote environment
Create a user named webhost
with sudo
privileges:
[local]$ ssh root@{host} "bash -s" -- < scripts/setup_webhost.sh
Configure the server:
[local]$ ssh webhost@{host}
# You'll be prompted to update your password - do so, then log in again
[server]$ git clone https://github.com/newmediacollective/Sites.git
[server]$ cd Sites
[server]$ source scripts/setup_server.sh
- This will create a virtual environment in
app/.env
- All
python
commands should be run with your virtual environment activated - Activate with
source app/.env/bin/activate
- Deactivate with
deactivate
- All
- This will also setup nginx and Let's Encrypt
- Everything will be run from the
webhost
user as part of the nginx group,www-data
4. Create your site
[server][env]$ python app/site_manager.py create -s "{host}" -t "site title" -d "site description" -f "date format"
- This will create the directory
app/sites/{host}
that contains all your site's data - It will also generate a secret key in
app/sites/secret.txt
that we'll use to sign tokens- To post to your site, you'll need to provide a valid token (more on that later)
- You can update your site's title, description, and other information in the
app/sites/{host}/data/properties.json
file
5. Encrypt the traffic
[server]$ sudo certbot --nginx -d {host} -d www.{host}
We'll update the nginx config, so you can ignore the error that cerbot failed to install the certificate.
6. Start it up
Update the nginx config in /etc/nginx/nginx.conf
for every site defined in
app/sites
:
[server]$ sudo python3 app/site_manager.py update_nginx
Start nginx (to serve the static site) and a gunicorn daemon (to serve the flask app for image uploads):
[server]$ ./scripts/start_services.sh
Generate your site:
[server][env]$ python app/content_manager.py {host} generate
You should see an empty site with your title and description at https://{host}
- Site
- The site is served as static content from nginx out of the
/home/webhost/Sites/app/sites/{host}/content
directory - Site data is stored in
app/sites/{host}/data
- HTML pages are generated by the
app/content_manager.py
script
- The site is served as static content from nginx out of the
- Posting
- Posting remotely is handled by a Flask app served by a Gunicorn daemon
- Images should be uploaded as a common type (png, jpg, etc.)
- Images are converted to progressive jpgs using ImageMagick
- Videos should be uploaded as a common type (mp4)
- Videos are converted to mp4s (if they aren't already)
- Video thumbnails are pulled from timestamp 0
- You can replace the image in the
/thumbnails
directory if needed
- You can replace the image in the
- Routing
- All HTTP traffic is redirected to HTTPS
- All www urls are redirected to non www
- All trailing slash urls are rewritten to non trailing slash urls
There are a couple tools to help manage your site(s).
You can sync your site content to and from your remote server with:
[local][env]$ python app/content_manager.py {host} pull
[local][env]$ python app/content_manager.py {host} push
After you create a new site on the server, you'll want to pull it down locally before making posts.
Pulling is useful when you've posted directly to your remote server, and you want to pull the latest version of your site to your local machine. Pushing is useful when you've created a post on your local machine and want to update your public site.
Note: Pushing and pulling will overwrite the destination!
To create a post locally, use:
[local][env]$ python app/content_manager.py {host} create text /path/to/text.md
[local][env]$ python app/content_manager.py {host} create image /path/to/image.jpg
[local][env]$ python app/content_manager.py {host} create video /path/to/video.mp4
To post directly to your server, use:
[local]$ ./scripts/post_text.sh {host} /path/to/text.md "location" "date"
[local]$ ./scripts/post_image.sh {host} /path/to/image.jpg "caption" "location" "date"
[local]$ ./scripts/post_video.sh {host} /path/to/video.mp4 "caption" "location" "date"
Fill in the app/sites/{host}/content/icons
directory with the following files
so your site will automatically serve a favicon and Apple touch icon:
favicon-0.png (64x64)
apple-touch-icon-0.png (180x180)
If you ever need to update them, simply bump the number to 1, 2, 3, etc, and
update the icon_version
in properties.json
.
If you ever edit anything in app/sites/{host}/data
, you can regenerate your
site with:
[local][env]$ python app/content_manager.py {host} generate
Managing multiple sites on the same machine is pretty simple (you can host them on different servers if you prefer).
1. Create a new site on your server
[server][env]$ python app/site_manager.py create -s "{new_host}" -t "new site title"
2. Encrypt the traffic
[server]$ sudo certbot --nginx -d {new_host} -d www.{new_host}
3. Update and restart nginx
[server]$ sudo python3 app/site_manager.py update_nginx
[server]$ sudo systemctl restart nginx
To run the app locally in debug mode, use:
[local][env]$ python app/app.py
This will run the app at http://localhost:5000
.
You can open your site locally with:
[local]$ open app/sites/{host}/content/views/index.html
You can test posting directly to the server locally with:
[local]$ ./scripts/post_text_local.sh {host} /path/to/text.md "location" "date"
[local]$ ./scripts/post_image_local.sh {host} /path/to/image.jpg "caption" "location" "date"
[local]$ ./scripts/post_video_local.sh {host} /path/to/video.mp4 "caption" "location" "date"
Note: Individual post pages don't work locally because they rely on nginx to
reroute their paths to the .html
files.
The site design is simple and inflexible, but there are already plenty of tools for managing complex sites. This solves the problem of posting text, photos, and videos to an https site and serving them as static content.
That said, feel free to fork the project and mess around with the template
directory - there are CSS files in template/content/styles
. Restructuring the
HTML requires code changes in app/post.py
.
Happy site building!