Setup
This guide describes how to get a webapp, derived from baselayer, up
and running. A simple example of such an application is provides as a
template application.
Clone that application, and then proceed with the following instructions.
Installation
A Python 3.8 or later installation is required.
Install the following dependencies: Supervisor, NGINX, PostgreSQL, Node.JS
On macOS
Using Homebrew:
brew install supervisor postgresql nodeIf you want to use brotli compression with NGINX (better compression rates for the frontend), you can install NGINX with the
ngx_brotlimodule with this command:brew tap denji/nginx && brew install nginx-full --with-brotli. If you already had NGINX installed, you may need to uninstall it first withbrew unlink nginx. Otherwise, you can install NGINX normally withbrew install nginx.Start the postgresql server:
to start automatically at login:
brew services start postgresqlto start manually:
pg_ctl -D /usr/local/var/postgres start
Using MacPorts:
port install nginx +realip postgresql13-serverStart the postgresql server:
port load postgresql13-server
Port Number Configuration with macOS
The default port number used by the baselayer app is 5000, but this port is not available for use with all operating systems. Port 5000 is not free for the latest macOS version, Monterey.
If 5000 is not available, you will need to modify the config.yaml file to use another port. For example, you may use:
ports:
app: 5700
See below for more information on modifying the baselayer configuration file.
On Linux
Using
apt-get:sudo apt-get install supervisor postgresql libpq-dev nodejsIf you want to use brotli compression with NGINX (better compression rates for the frontend), you have to install NGINX and the brotli module from another source with:
sudo apt remove -y nginx nginx-common nginx-core sudo add-apt-repository ppa:ondrej/nginx-mainline -y sudo apt update -y sudo apt install -y nginx libnginx-mod-brotli
Otherwise, you can install NGINX normally with
sudo apt-get install nginx.It may be necessary to configure your database permissions: at the end of your
pg_hba.conf(typically in/etc/postgresql/13.3/mainor/var/lib/pgsql/data), add the following lines and restart PostgreSQL (sudo service postgresql restartorsystemctl reload postgresql):# CONNECTION DATABASE USER ADDRESS METHOD host template_app template_app localhost trust host template_app template_app_test localhost trust host all postgres localhost trust
Substitute the correct database name and user, as defined in your
config.yaml.If you use IPv6,
localhostbecomes::1/128.
Building the baselayer database
Initialize the database with
make db_init(also tests that your permissions have been properly configured).Run
maketo start the server and navigate tolocalhost:5000. If you have modified the baselayer configuration to use a different app port, you should instead navigate tolocalhost:PORTNUMBER.
Configuration
Customize
config.yaml(seeconfig.yaml.defaultsfor all options).Always modify
secret_keybefore deployment!
If you want other users to be able to log in:
Provide Google auth credentials, obtained as described in
config.yaml, or configure another provider (see below).
Sign-in providers
Sign-in is handled by python-social-auth,
which ships backends for Google, ORCID, GitHub, Slack, SAML, generic OpenID
Connect and many others. With no configuration, Google is used, taking its
credentials from server.auth.google_oauth2_key / _secret.
To offer something else, list it under server.auth.backends. Each entry needs
the backend’s own name, plus the dotted path to its class. The name is what
appears in /login/<name>, and what its SOCIAL_AUTH_<NAME>_* settings are
keyed on:
server:
auth:
backends:
- name: orcid
class: social_core.backends.orcid.ORCIDOAuth2
key: ...
secret: ...
label: Sign in with ORCID
- name: my-iam
class: social_core.backends.open_id_connect.OpenIdConnectAuth
key: ...
secret: ...
settings:
oidc_endpoint: https://iam.example.org
Anything under settings is exported as SOCIAL_AUTH_<NAME>_<KEY>, so a
provider speaking standard OpenID Connect needs no code at all. A provider that
does need code, for example a bespoke federation endpoint, can subclass
social_core.backends.oauth.BaseOAuth2 anywhere importable and be named here by
its dotted path; it does not have to live in baselayer.
The login page shows one button per provider, in the order listed. In debug mode, where sign-in succeeds without contacting any provider, the stand-in takes the name of the first provider you list, so development and production exercise the same login page and the same routes.
Signing in with more than one provider
Returning with a provider you have used before always lands you back in the same account, even if you have since changed your email address there.
Returning with a different provider is recognised as the same person only when the second provider reports an email address matching the account and vouches that the address is yours. Otherwise you get a second, separate account.
Most providers say whether they have verified an address, and some verify but
never say so. For one you are confident about, add trust_email and its
addresses will be accepted for matching:
- name: orcid
class: social_core.backends.orcid.ORCIDOAuth2
trust_email: true
Leave it off for anything else. There is also use_unique_user_id, on by
default, which keeps accounts tied to the provider’s own id for the user rather
than to their email address; there is rarely a reason to change it.
GitHub needs neither: it verifies addresses but python-social-auth drops the
flag, so trust_email there would trust something nobody checked. Use the
backend below instead, which reports the flag GitHub actually returned:
- name: github
class: baselayer.app.backends.github.VerifiedEmailGithubOAuth2
key: ...
secret: ...
Username generation
When server.auth.username_is_email is set to True (the default), the user’s email address is used as their username.
When set to False, the username is derived from the username field provided by the OAuth provider. For Google OAuth2, this is typically the local part of the email address (everything before @, e.g., john.doe from john.doe@example.com). If that username is already taken, a random suffix is appended until a unique username is found. This logic is handled by the social_core library.
Launch
Launch the app with make run.
Deployment options
The default configuration file used can be overridden by setting the FLAGS environment variable:
FLAGS="--config=myconfig.yaml" make run
Debug mode
By default, baselayer runs in debug mode. In debug mode:
The server binds to localhost, not 0.0.0.0 (i.e., is not publicly accessible).
Authentication always succeeds, but does not connect to any oauth provider.
Code changes cause automatic reloads of the app, and recompilation of Javascript bundles.
When switching to production mode (debug set to False in the config
file):
The server binds to 0.0.0.0.
Javascript bundles are not compiled; they need to be pre-compiled using
make bundle.