Commit 7ee623ae authored by Silvio Rhatto's avatar Silvio Rhatto
Browse files

Merge branch 'feature/deployment' into 'main'

Feat: deployment procedure

See merge request tpo/onion-services/sponsor123-landing-page!12
parents 858da80e 6165d195
Loading
Loading
Loading
Loading

.dockerignore

0 → 100644
+2 −0
Original line number Diff line number Diff line
.git
public
+12 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ public
*.pyc
__pycache__

i18n/compiled
i18n

### Emacs ###
# -*- mode: gitignore; -*-
@@ -76,4 +76,15 @@ company-statistics-cache.el

# anaconda-mode
anaconda-mode/

# Compiled localized content
content/contents+*.lr

# Environment file
.env

# Python virtual environment
venv

# Python requirements
requirements.txt
+19 −0
Original line number Diff line number Diff line
# This CI configuration is used for landing page deployment in external GitLab
# instances.
#
# To use it, go into the "CI/CD settings" of that repository and input
# ".gitlab-ci-deployment.yml" in the "CI/CD configuration file" field under the
# "General pipelines" section.
---
# Right now we're sticking to Python 3.8 due to dependency issues.
image: python:3.8-bullseye

pages:
  script:
    - scripts/provision
    - scripts/build
  artifacts:
    paths:
      - public
  only:
    - main

Dockerfile

0 → 100644
+75 −0
Original line number Diff line number Diff line
#
# Dockerfile for Landing Pages development.
#

FROM python:3.8-bullseye AS landing
MAINTAINER Silvio Rhatto <rhatto@torproject.org>

# Basic project environment
ENV APP="${COMPOSE_PROJECT_NAME:-sponsor123-landing-page}"
ENV APP_BASE="/srv"
ENV SHELL="/bin/bash"

# UID and GID might be read-only values, so use non-conflicting ones
ARG CONTAINER_UID="${CONTAINER_UID:-1000}"
ARG CONTAINER_GID="${CONTAINER_GID:-1000}"

WORKDIR ${APP_BASE}/${APP}

# Copy the project files and run the provision script
COPY . ${APP_BASE}/${APP}
RUN  ${APP_BASE}/${APP}/scripts/provision
RUN  rm -rf /var/lib/apt/lists/*

# Switch to a regular user
RUN groupadd -r -g ${CONTAINER_GID} ${APP} && \
    useradd --no-log-init -r -u ${CONTAINER_UID} -g ${APP} ${APP} && \
    mkdir -p /home/${APP} && chown ${APP}. /home/${APP}
RUN chown -R ${APP}.${APP} ${APP_BASE}/${APP}
USER ${APP}

# Initial build: needed to deploy the image as an standalone application.
# During development, it's useful to install the Python virtualenv.
RUN ${APP_BASE}/${APP}/scripts/build

# Use the Lektor default HTTP port
EXPOSE 5000

# The entrypoint for the development mode
ENTRYPOINT ["scripts/server"]

# This reduces the image size, but without this folder the container startup
# will take longer when running in development mode ("lektor server") as the
# ENTRYPOINT.
#RUN rm -rf /home/${APP}/.virtualenvs/onion-support-landing-page

FROM landing AS apache

# Include Apache
USER root
RUN apt-get update && apt-get install -y apache2 && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

# Set the environment for Apache
# In Debian it won't suffice to set some of these as environment variables:
# they should be included at /etc/apache2/envvars instead.
RUN echo "export APACHE_RUN_USER=${APP}"                                                 >> /etc/apache2/envvars
RUN echo "export APACHE_RUN_GROUP=${APP}"                                                >> /etc/apache2/envvars
RUN echo "export APACHE_LOG_DIR=${APP_BASE}/${APP}/log"                                  >> /etc/apache2/envvars
RUN echo "export APACHE_LOCK_DIR=${APP_BASE}/${APP}/lock"                                >> /etc/apache2/envvars
RUN echo "export APACHE_RUN_DIR=${APP_BASE}/${APP}/run"                                  >> /etc/apache2/envvars
RUN echo "export APACHE_PID_FILE=${APP_BASE}/${APP}/pid/apache2.pid"                     >> /etc/apache2/envvars
RUN echo -n "<Directory ${APP_BASE}/${APP}/public>\nAllowOverride All\n</Directory>\n"    > /etc/apache2/conf-available/allow_override.conf
RUN echo -n "<Directory ${APP_BASE}/${APP}/public>\nOptions +Includes\n</Directory>\n"    > /etc/apache2/conf-available/options_includes.conf
RUN echo -n "<Directory ${APP_BASE}/${APP}/public>\nRequire all granted\n</Directory>\n"  > /etc/apache2/conf-available/require.conf
RUN echo "ServerName ${APP}"                                                              > /etc/apache2/conf-available/servername.conf
RUN echo "DocumentRoot ${APP_BASE}/${APP}/public"                                         > /etc/apache2/conf-available/documentroot.conf
RUN echo "Listen 5000"                                                                    > /etc/apache2/conf-available/listen.conf
RUN a2enconf allow_override options_includes require servername documentroot listen

USER ${APP}

RUN mkdir -p log lock run pid

# Serve the statically built site
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
+162 −0
Original line number Diff line number Diff line
# Sponsor 123 Landing Page

## Dependencies

This project relies on [Lektor](https://www.getlektor.com/)
and some dependencies detailed at the
[TPA CI templates](https://gitlab.torproject.org/tpo/tpa/ci-templates) project.

A [provision script](scripts/provision) is available as an example of dependency
installation from a [Debian][] stable system, and can be adapted to your own environment
and needs.

[Debian](https://www.debian.org)

## Building

Several parts of the site are configured through environment variables during the lektor build. These variables are:
@@ -17,6 +29,8 @@ LEKTOR_FOREGROUND_COLOR=FF0000 LEKTOR_BACKGROUND_COLOR=FF7700 LEKTOR_BUTTON_COLO
```

It's a long build command, but ideally would only be run by a script.
An [example script](scripts/build) is provided which calls `lektor` after ensuring
additional dependencies are installed (see below).

## Adding a new RTL language

@@ -29,3 +43,151 @@ If you end up enabling translation support for a right-to-left (RTL) language, b
```

The `page.html` template uses this databag to decide if the page should be displayed as RTL. If your new RTL language isn't in the databag, it will be rendered "mirrored" to how it should be, like left-to-right languages are.

## Developing

There are some documented ways in how to setup your development environment for
this project:

1. Using [Docker][] and [Docker Compose][].
2. Using [GitLab Runner][].
3. Using [PyEnv][].
4. Setting up your environment manually.

They are explained in the following sections, and of couse you can also proceed
with your own procedure if nothing else fits. They're tested with [Debian][]-like
operating systems.

The procedures can also be executed inside a virtual machine, preferably using
[Debian][].

### Environment file

The `LEKTOR_*` and other environment variables can be stored in the `.env`
configuration file.

### Helper scripts

Also, number of helper scripts are available to aid development, testing and deployment:

* `scripts/provision-docker-compose`: installs [Docker Compose][] in a [Debian][]-based
  system.
* `provision-gitlab-runner`: installs [GitLab Runner][] in a [Debian][]-based system.
* `provision-pyenv`: install [PyEnv][] locally at user's `$HOME/.pyenv`.
* `provision`: setus up the basic system environment (system-wide packages).
* `env`: sets up the basic [Python][] environment needed to build the landing pages
  (local Python packages).
* `build`: the actual build script.
* `build-with-gitlab-runner`: build the landing page using [GitLab Runner][].
* `server`: wrapper around [lektor server](https://www.getlektor.com/docs/cli/server/).
* `server-public`: basic HTTP server used to inspect build artifacts stored at
  the `public/` folder.

[Python]: https://www.python.org

### Using [Docker][] and [Docker Compose][]

Make sure you have [Docker][] and [Docker Compose][] properly installed.
The [provision-docker-compose](scripts/provision-docker-compose) script serves
as an example in how to do that.

Then proceed as usual:

    docker-compose up

This should build the container image and bring a service container running
`lektor server` with a HTTP server listening at [http://localhost:5000][].

As an alternative, it's possible to use the [provided Dockerfile][Dockerfile]
for serving a statically built landing page.

[Docker]: https://docs.docker.com
[Docker Compose]: https://docs.docker.com/compose
[http://localhost:5000]: http://localhost:5000

### Using [GitLab Runner][]

The [GitLab Runner][] approach is aimed to test the [CI configuration for
deployment](.gitlab-ci-deployment.yml) directly through a [GitLab Runner][]
instance locally installed in your computer.

Install [GitLab Runner][] according to the [docs](https://docs.gitlab.com/runner/install/)
or using the provided [provision-gitlab-runner](scripts/provision-gitlab-runner) script.

Then proceed running the corresponding build script:

    scripts/build-with-gitlab-runner

If the build is successful, the resulting site will be available at the `public/` folder
and can be browser using a HTTP server such the one provided by this repository which
listens on [http://localhost:5000][]:

    scripts/server-public

[GitLab Runner]: https://docs.gitlab.com/runner

### Using [PyEnv][]

Another approach is to use [PyEnv][] to setup your environment with the required
[Python][] version needed to build the landing page.

The [provision-pyenv](scripts/provision-pyenv) script has an example in how to
do that, which should run after the [provision](scripts/provision) script:

    scripts/provision
    scripts/provision-pyenv

Then you can simply use the provided [build](scripts/build) script:

    scripts/build

You can also manually invoke [Lektor][] like this:

    source scripts/env
    lektor clean --yes
    lektor server

The [virtualenv][] is created by default inside of your `$HOME/.virtualenvs`
folder, but that can be customized with the `$VENV` shell environment variable.

[PyEnv]: https://github.com/pyenv/pyenv
[virtualenv]: https://docs.python.org/3/library/venv.html

### Setting up your environment manually

You might use this approach if you prefer a customized way to install the
required [Python][] version and/or you already have your own [Lektor][]
workflow.

First install the required [Python][] version, whose exact number can be found
in the [Dockerfile](Dockerfile) or at the [.gitlab-ci-deployment](.gitlab-ci-deployment)
file.

A suggested way is running this command sequence:

    lektor-venv && source .env && lektor clean --yes && lektor server

where `lektor-venv` is a [bash][] function that sets up a `venv`, and `.env` is
literally just a file exporting the `LEKTOR_*` environment variables:


```shell
lektor-venv ()
{
    VENV="${VENV:-$HOME/.virtualenvs/onion-support-landing-page}

    [ -d "$VENV" ] && source "$VENV/bin/activate" && \
      echo 'virtualenv found in "$VENV" and activated' && return;

    python3.8 -m venv "$VENV" && source "$VENV/bin/activate" && \
      pip install --upgrade pip lektor && echo 'virtualenv set up in "$VENV" and activated'
}
```

Make sure to:

* Replace `python3.8` with the required [Python][] version, if needed.
* Set the `$VENV` shell environment variable according to your preference.

[Lektor]: https://www.getlektor.com
[bash]: https://www.gnu.org/software/bash
Loading