Skip to content

Commit caf762b

Browse files
committed
Interstitial commit for massive documentation extensions.
Signed-off-by: Josh Berkus <josh@agliodbs.com>
1 parent 4397582 commit caf762b

File tree

3 files changed

+371
-0
lines changed

3 files changed

+371
-0
lines changed
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
---
2+
title: "Configuration"
3+
linkTitle: "Configuration"
4+
weight: 2
5+
description: >
6+
Setting up and configuring Elekto for operation
7+
---
8+
9+
# Configuration and Setup
10+
11+
Elekto's configuration is divided into three parts:
12+
13+
1. Oauth and GitHub configuration
14+
2. Runtime environment
15+
3. Per-election configuration
16+
17+
This document covers the first two, which consists of the items that need to be configured before Elekto will run. The third part is covered in the [Administrator Guide].
18+
19+
## Oauth and Repository Configuration
20+
21+
Elekto relies on an external Oauth provider for user authentication, by design. This provider must be configured to accept authentication requests from Elekto. You may only have one Oauth provider per Elekto instance, as authentication happens before selecting an election.
22+
23+
You must also configure the repository that contains the election metadata (hereafter "the repo") to push changes to Elekto.
24+
25+
Currently, the only Oauth provider offered is GitHub. Contributions of additional providers are extremely welcome.
26+
27+
### GitHub Setup
28+
29+
#### GitHub Oauth
30+
31+
You must set up an "Oauth Application" that Elekto can use. In GitHub, this is under Settings-->Developer Tools-->Oauth Applications. Note that Oauth Apps are belong to *accounts* rather than organizations, so you'll want to set up an account with shared access in your infra team. We also recommend setting up a separate Oauth App for Elekto rather than re-using one created for other purposes, and giving each Elekto instance its own secret key.
32+
33+
The Oauth App must have the following settings:
34+
35+
*
36+
37+
Having configured this, you can populate GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET in Elekto's runtime environment.
38+
39+
#### GitHub Repository Webhook
40+
41+
In order to receive changes from the repo, you need to add a webhook that pushes changes whenever you merge. Webhooks are under "settings" for the individual repository (which also means you must be a repo onwer).
42+
43+
The Webhook should have the following settings:
44+
45+
* Push webhook
46+
* JSON data format
47+
* Use TLS
48+
*
49+
* Shared Secret set to the same as META_SECRET
50+
51+
This last "secret" is an arbitrary string that authenticates the push to the Elekto server. It can be any string, such as one created by a password generator or a passphrase you like. This string then gets set in META_SECRET.
52+
53+
## The Environment File
54+
55+
Elekto is designed to accept its runtime configuration as ENV variables in its shell environment. A sample `.env.example` file can be found in the base directory of the Elekto source. These ENV configuration variables are not expected to change frequently, or at all, for any particular running Elekto instance. Changing them generally requires restarting Elekto.
56+
57+
All of these env variables need to be set before starting Elekto as a uwsgi application, or even in developer mode; without them, Elekto will error out and refuse to start. You can set this up however you please:
58+
59+
* as the `.bashrc` for the elekto application user
60+
* as ENV variables for a container running Elekto
61+
* preloaded in a systemd unit file
62+
* injected through a ConfigMap and a Secret into an Kubernetes pod
63+
64+
Since we use ENV for Elekto configuration, this does mean that Elekto must be launched under a shell.
65+
66+
### ENV Variables
67+
68+
What follows are the ENV variables that must be set for Elekto to run.
69+
70+
#### Application Information
71+
72+
**APP_NAME**
73+
74+
*Required* Name of the Elekto instance you are running. Displays in some parts of the UI. For user information only.
75+
76+
Example: `k8s.elections`
77+
78+
**APP_ENV**
79+
80+
*Optional* Status of this Elekto instance, for CI/CD purposes. Not used internally by Elekto.
81+
82+
Example: `production` or `development`
83+
84+
**APP_KEY**
85+
86+
*Optional* Seed string for Flask encryption if running Flask in standalone mode. Not required if fronting with an HTTPS webserver.
87+
88+
Example: ``
89+
90+
FIXME
91+
92+
**APP_DEBUG**
93+
94+
*Required* Whether to run in Debug mode for troubleshooting purposes. In Debug mode, will output stack traces for errors and reload templates.
95+
96+
Example: `True` or `False`
97+
98+
**APP_URL**
99+
100+
*Optional* URL of the Elekto instance. Used by some uwsgi and/or Nginx configurations. Not used internally by Elekto.
101+
102+
Example: `http://elections.knative.dev`
103+
104+
**APP_PORT**
105+
106+
*Optional* Used in some uwsgi start scripts, and when running Flask in standalone mode. Port on which to serve Elekto.
107+
108+
Example: `5000`
109+
110+
**APP_HOST**
111+
112+
*Optional* Used in some webserver startup scripts, and by the Flask server in standalone mode. Name of the host served by this Elekto instance.
113+
114+
Example: `localhost`
115+
116+
**APP_CONNECT**
117+
118+
*Optional* Whether to serve uwsgi over HTTP or via a local unix socket. Used by some startup scripts; see `entrypoint.sh` for an example.
119+
120+
Example: `http` or `socket`
121+
122+
#### Database Connection
123+
124+
**DB_CONNECTION**
125+
126+
*Required* Which database connection type to use. Currently only postgresql, mysql, and sqlite are supported.
127+
128+
Example: `postgresql`, `mysql`, or `sqlite`
129+
130+
**DB_HOST**
131+
132+
*Required* The URL, IP, or hostname of the database server. Ignored if using SQLite (set to `N/A`).
133+
134+
Example: `pgdb-1a.prod.elekto.dev`
135+
136+
**DB_PORT**
137+
138+
*Required* The network port for the database server. Ignored if using SQLite (set to `1001`).
139+
140+
Example: `3306`
141+
142+
**DB_PATH**
143+
144+
*Optional* Used only for SQLite. Path to the database filesystem.
145+
146+
Example: `/var/db/elekto-db`
147+
148+
**DB_USERNAME**
149+
150+
*Required* Login user for the Elekto database. Not used by SQLite.
151+
152+
Example: `elekto`
153+
154+
**DB_PASSWORD**
155+
156+
*Required* Authentication password for the Elekto database. Not used by SQLite.
157+
158+
Example: `1a6e4b3f55dc`
159+
160+
#### Repository Configuration
161+
162+
**META_REPO**
163+
164+
*Required* GIT clone URL for the repository which contains the election configurations. Should be the `.git` link, not the `.html` one.
165+
166+
Example: `https://github.com/kalkayan/k8s.elections.meta.git`
167+
168+
**ELECTION_DIR**
169+
170+
*Required* Directory, relative to the Git repository root, containing the set of election subdirectories. Can be an arbitrarily deep path. Do not use a leading or trailing `/`.
171+
172+
Example: `elections`, `gov/steering/elections`
173+
174+
**META_DEPLOYMENT**
175+
176+
*Optional* Reserved for future advanced configuration use.
177+
178+
Example: `local`, `sidecar`
179+
180+
**META_PATH**
181+
182+
*Required* Local file location at which to store a clone of the election data repository. This directory will be created by Elekto at sync time, so the application must have the ability to write to the parent directory. May be absolute or relative; if relative, will be under the eletko source directory. Defaults to `meta`. For containers, a directory under `/tmp` is recommended to make sure the location is writeable.
183+
184+
Example: `meta`, `/tmp/meta`
185+
186+
**META_BRANCH**
187+
188+
*Required* Which git branch has the merged version of the election data. Defaults to `main`.
189+
190+
Example: `main`, `master`, `prod`
191+
192+
**META_SECRET**
193+
194+
*Required* The shared secret string used in the Github webhook for updates of the election data repository. Can be set to anything you like; we recommend a random md5 string or generated password.
195+
196+
Example: `92a488d11c0d27bbfea0a97e3332e08a`
197+
198+
#### Oauth Settings
199+
200+
At this time, there are only settings available for GitHub because other Oauth sources haven't been implemented. When other sources get added to Elekto, each will get their own configuration variables.
201+
202+
**GITHUB_REDIRECT**
203+
204+
*Required* Flask path for the GitHub authentication callback. Defaults to `/oauth/github/callback`, and there's no good reason to change it.
205+
206+
Example: `/oauth/github/callback`
207+
208+
**GITHUB_CLIENT_ID**
209+
210+
*Required* The Client ID from the GitHub Oauth Application.
211+
212+
Example: `0b9138c0b2ffeefd9fc1`
213+
214+
**GITHUB_CLIENT_SECRET**
215+
216+
*Required* The Client Secret from the GitHub Oauth Application.
217+
218+
Example: `dd37278f8e9d57571590ad9288f0aae62228c2e8`
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
title: "Installation"
3+
linkTitle: "Installation"
4+
weight: 2
5+
description: >
6+
Full installation documentation
7+
---
8+
9+
# Installation Concepts
10+
11+
For Elekto to run in production, you need the following small application stack:
12+
13+
* The Elekto python/flask/uwsgi application
14+
* A backing SQL database instance
15+
* A web proxy such as Nginx or Kubernetes Ingress
16+
* A GitHub repository
17+
* An Oauth authentication source
18+
19+
Elekto can be installed either as a native application, or as a container.
20+
21+
## Installing Requirements and Python Binaries
22+
23+
Elekto is a Python/Flask/uwsgi application developed in Python 3. Building it from source requires the following prerequisites, which should be installed using your OS's packaging system:
24+
25+
* Python3 Pip and supporting build tools (like gcc), or Conda
26+
* uwsgi server
27+
* Database client libraries for your chosen database (see below)
28+
* git
29+
30+
Having installed those prerequisites, you can now install the python requirements using Pip, which will build the python source:
31+
32+
```bash
33+
# Installation with pip
34+
pip install -r requirements.txt
35+
36+
# Installation with Conda
37+
conda env create -f environment.yml && conda activate elekto
38+
```
39+
40+
Please check the above build process carefully for error messages; the only acceptable errors are (a) warnings about out-of-date versions and (b) missing database libraries for the databases you're not using.
41+
42+
It is completely possible that you could run Elekto using fastcgi instead of uwsgi, but at this time we have no documentation on how to do this.
43+
44+
## Backing SQL Database
45+
46+
Github stores ballots and some metadata in a designated SQL database, which is up to you to install and run. Currently Elekto supports the following:
47+
48+
* PostgreSQL
49+
* MySQL (and its forks)
50+
* SQLite
51+
52+
However, as Elekto uses SQLAlchemy, it can potentially support any SQL database that SQLAlchemy supports. Adding new databases will require a PR to Elekto.
53+
54+
Database requirements are very light, so it is completely feasible to run the database on the same server as the python application. The database server needs less than 2 CPUs, 1GB memory, and 25GB storage. You can also use a cloud database service; the included database support was chosen specifically because there are multiple cloud database services available. In that case, you are likely to use the smallest size of cloud database available.
55+
56+
The Elekto database user needs to have permissions to create tables. The database must be configured with user/password login. Other forms of authentication are not yet supported.
57+
58+
The Elekto application will not run if the database is unavailable. The ballot data contained in the database is not stored anywhere else, and as such is unrecoverable if the database is lost. For this reason, it is up to the administrator to set up and manage backups and high availability. This is particularly a concern for SQLite, which is an embedded database; you will need to set up cron jobs on the server to back this up.
59+
60+
## Web Server
61+
62+
Elekto runs in the python uwsgi web application server. Uwsgi is not very scalable, though, and does not handle SSL connections. As such, for anything other than developer mode, we recommend that you put a web server in front of it.
63+
64+
Nginx works well for this, whether as a standalone or as part of Kubernetes Ingress. See the sample Nginx configuration in the installation directory of the Elekto repository for an example setup. If running directly on a host with an Nginx proxy, you'll want to run Eletko in "socket" connection mode. Other web servers would also work, but Nginx is the only sample configuration supplied.
65+
66+
On Kubernetes, you'll want to access Elekto via Ingress. See `installation/deployment` for an example of this. In a Kubernetes setup, you want to run Elekto in http mode.
67+
68+
## GitHub Repository
69+
70+
Elekto's workflow is GitOps-based. This means that, in order to use Elekto, you must have a GitHub (GitLab TBD) repository for Elekto to attach to. This must be a repository you own and have administration rights on, as you will be setting up a webhook and directories.
71+
72+
It does *not* need to be a repository that's exclusively dedicated to Elekto. Most organizations using Elekto place its election metadata into a subdirectory of a repository that's used for other community documents (e.g. `knative/community/elections`). Given that Elekto will refresh for every webhook push, however, it's probably better if it's not a repository that gets multiple commits per hour.
73+
74+
See [Configuration]() for how to set up this GitHub repository, and the [Administration Guide]() for what files go into it.
75+
76+
## Oauth Authentication Source
77+
78+
Elekto does not maintain user authentication; by design, it relies on an outside Oauth source for user login. Currently the only Oauth source supported is GitHub. If you want to add other sources, contributions are very welcome.
79+
80+
See Configuration for how to configure this in GitHub.
81+
82+
## Other System Requirements
83+
84+
Elekto does not require elevated privileges to run, so for security we recommend running it under an elekto, www, or python application account with restricted permissions.
85+
86+
Elekto caches a copy of the election respository on disk, and as such needs a file location to which it can write, with storage equal to the storage size of a git clone of that repository.
87+
88+
If you've completed everything in Installation, please proceed to [Configuration]().

content/en/docs/Overview/goals.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
title: "Design Goals"
3+
linkTitle: "Goals"
4+
weight: 1
5+
description: >
6+
Reasons behind the Elekto design
7+
---
8+
9+
Elekto was originally built to support the Kubernetes Steering Committee elections, supporting the existing workflow of that community. It's also intended to avoid several chronic issues with usage of the CIVS election system.
10+
11+
Before adopting, or contributing to Elekto, please read these principles as the project is very unlikely to accept features which transgress any of them.
12+
13+
## Preference Elections for Small Organizations
14+
15+
Elekto is designed only to support "preference elections" where voters rank candidates. We have found preference elections to offer better outcomes than other methods, such as plurality.
16+
17+
Currently, only the Condorcet preference election algorithm is supported, but contributions of other preference election accounting methods would be very welcome.
18+
19+
Elekto is not designed to support public governmental elections, or any election that might attract either thousands of voters, or a determined effort to compromise the system.
20+
21+
## Simplicity
22+
23+
The project is designed to be an extremely simple, lightweight web application. Simplicity makes it easy to install and support in a variety of environments and platforms. This means that organizations can run Elekto as a microservice, on their own, instead of requiring a paid, hosted service.
24+
25+
Simplicity also makes Elekto easy to fork and modify, as well as contribute to. We chose [Flask]() as our framework with this in mind. It's also why our container image is a simple, unified image.
26+
27+
This does mean that changes that would substantially increase the complexity of Elekto -- such as a theme engine or porting it to Django or decomposing it into a half-dozen scalable subservices -- are unlikely to be accepted in the main project.
28+
29+
## No Email
30+
31+
Elekto does not send any email, or other types of messages, to anyone. 100% of Elekto interaction is via GitOps and the Web UI.
32+
33+
This requirement is based on experience with other election systems. Email today is a singularly unreliable way to deliver ballots or other election messages, and other channels aren't much better. Anyone who has administered an election under CIVS can tell you that 80% of their work is troubleshooting email delivery issues.
34+
35+
## Microservice
36+
37+
Elekto is intended to be run as a microservice, with one Elekto instance per organization or team. It is not intended to run as a multi-tenant service; instead, run a separate Elekto instance for each user.
38+
39+
Each Elekto instance connects to only one metadata repository, one database, and one Oauth source. Again, if you need multiple configurations, the solution is to run multiple Elekto instances.
40+
41+
Elekto supports any number of elections for that one organization.
42+
43+
## GitOps Administration
44+
45+
The practice of defining adminstrator actions and application configuration via changes to files in a Git repository is called "GitOps". Elekto administration is based entirely on GitOps, which offers the following advantages:
46+
47+
* Eliminates multiple webforms, keeping the codebase smaller
48+
* Allows organizations to define their change and approval workflow through their git repo, including owner roles and multi-stage approval and revision
49+
* Provides a transparent, long-term historical record of any and all election setup changes
50+
* Unifies documentation and configuration
51+
* Reduces dependency on database hosting
52+
53+
As such, the only data in Elekto that does not live in a git repo is data that needs to be private/secret: ballots, raw election results, and exception requests.
54+
55+
## Transparency
56+
57+
Elekto is aimed at public open source projects, which means that complete transparency of all election steps is required and provided. As such, the metadata git repo and the Elekto instance are expected to be publicly readable, and no provisions have been made for running Elekto using private repos or webservers on closed networks.
58+
59+
Transparency is also carried out in other design decisions. For example, while only designated voters can vote in an election, any user (or any authenticated visitor) can view the details of any election.
60+
61+
## Secret Ballot
62+
63+
Voters must be able to vote without their individual ballots being easily snoopable, whether by other voters, election officers, or infrastructure staff. In a small organization, infra maintainers and officers are usually voters and sometimes candidates themselves, and as such ballot identity needs to be hidden even from someone with direct access to the database.
64+
65+
Elekto was also built with the secondary requirement of allowing voters to re-cast their ballots up until the election deadline. However, individual ballot auditablilty was not a requirement, so it is not yet implemented (contributions welcome). Aggregate ballot auditablity is incompatible with secrecy, and as such is out of scope.

0 commit comments

Comments
 (0)