Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions docs/deploy/create_server.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ Create the server via the :ref:`host<hosting>`'s interface.
#. `Log into Linode <https://login.linode.com/login>`__
#. Click *Create Linode*

#. Set *Linux Distribution* to the latest Ubuntu LTS version
#. Set *Region* to *London, UK (eu-west)*
#. Set *Linux Distribution* to the latest Ubuntu LTS version
#. Select a *Linode Plan*
#. Set *Linode Label* to the server's FQDN (e.g. ``ocp99.open-contracting.org``)
#. Set *Add Tags* to either *Production* or *Development*
#. Set *Root Password* to a `strong password <https://www.lastpass.com/features/password-generator>`__, and save it to OCP's `LastPass <https://www.lastpass.com>`__ account
#. Under *Firewall*, if using Docker, click *Create Firewall* and :ref:`configure an external firewall from step 3<docker-firewall>`. Otherwise, select *No firewall - traffic is unprotected (not recommended)* from the dropdown.
#. Check *Backups*
#. Click *Create Linode* and wait a few minutes for the server to power on

Expand All @@ -58,11 +59,11 @@ Create the server via the :ref:`host<hosting>`'s interface.

#. Rename the "Swap Image" disk to "### MB Swap Image"

#. On the *Configurations* tab:
#. On the *Network* tab:

#. Click *Edit* for the "My Ubuntu ##.04 LTS Disk Profile" (or similar) configuration
#. Uncheck *Auto-configure networking* (skip if configuring a non-OCP server)
#. Click *Save Changes*
#. Click *Interface Settings*
#. Uncheck *Enable Network Helper* (skip if configuring a non-OCP server)
#. Click *Save*

#. Click *Power On*
#. Copy *SSH Access* to your clipboard
Expand All @@ -79,8 +80,6 @@ Create the server via the :ref:`host<hosting>`'s interface.

Linode can take a day to close the ticket. In the meantime, proceed with the instructions below. Once the ticket is closed, assign a specific address within the /64 block in the :doc:`network configuration<../develop/update/network>`.

#. If using Docker, :ref:`configure an external firewall<docker-firewall>`.

.. tab-item:: Hetzner Cloud
:sync: hetzner-cloud

Expand Down
14 changes: 14 additions & 0 deletions pillar/common.sls
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,28 @@ ssh:
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDG8dhMVvgH/tt9+VoyokyUg/iKVcZKMku8pYN6o8RoT8XKoyP/iyrUIl5HxolqIt+PJTpomYkA40eJ/0mN4/kRhr+tctZ+tUdo8/G8H42FG3McklL6XlwOdXRGIYC+NynF8YGws57J8YkM2oL9linkUZYpGpVkNew2aEg916HWWfGZktwuQa7knIwIhFr9FlvxxaZhdcQ7VJjnJOP0fLLr5WCVaiWDGjQ5cHJURcTBL+j+eTRpKFvk9BMKCAQyLkSEluT0QeESDMtR7sRHA54to1LDXRX0ky9cAQ6mxXWgpSpmHCuPVYpzOfoSd7b8aczDLUGBxq9EWOTS3UMUWJBX Yohanna (OCP)

# The default locale is en_GB rather than en_US for accidental, historical reasons.
{% if grains.osmajorrelease|int >= 26 %}
locale: en_US
{% else %}
locale: en_GB
{% endif %}

ntp:
- 0.uk.pool.ntp.org
- 1.uk.pool.ntp.org
- 2.uk.pool.ntp.org
- 3.uk.pool.ntp.org

# NTS used over NTP on Ubuntu 26.04+
nts:
time.cloudflare.com:
1.ntp.ubuntu.com:
2.ntp.ubuntu.com:
3.ntp.ubuntu.com:
4.ntp.ubuntu.com:
ntp-bootstrap.ubuntu.com:
context: iburst maxsources 1 nts certset 1

smtp:
relay: True
relay_address: noreply@noreply.open-contracting.org
Expand Down
24 changes: 19 additions & 5 deletions salt/apache/files/conf/letsencrypt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,31 @@
MDContactEmail sysadmin@open-contracting.org
MDCertificateAgreement accepted
MDCAChallenges http-01
{%- if grains.osmajorrelease|int >= 26 %}
{#- Store mod_md data outside /etc due to systemd filesystem sandboxing. #}
MDStoreDir /var/lib/apache2/md
{%- endif %}
{%- for directive, value in salt['pillar.get']('apache:modules:mod_md', {})|items %}
{{ directive }} {{ value }}
{%- endfor %}
</IfModule>

# generated 2023-06-28, Mozilla Guideline v5.7, Apache 2.4.52, OpenSSL 3.0.2, intermediate configuration
# https://ssl-config.mozilla.org/#server=apache&version=2.4.52&config=intermediate&openssl=3.0.2&guideline=5.7
# Omitted DHE-RSA-CHACHA20-POLY1305 (lowest priority).
<IfModule ssl_module>
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
{%- if grains.osmajorrelease|int >= 26 %}
# generated 2026-08-06, TLSRef Guideline v6.0, Apache 2.4.66, OpenSSL 3.5.5, intermediate config, gitrev=1b22dc6
# https://configurator.tlsref.org/#server=apache&version=2.4.66&config=intermediate&openssl=3.5.5&guideline=6.0
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLOpenSSLConfCmd Curves X25519MLKEM768:X25519:prime256v1:secp384r1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLCipherSuite TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
{%- else %}
# generated 2026-08-06, TLSRef Guideline v6.0, Apache 2.4.52, OpenSSL 3.0.2 (OLD: missing PQC hybrid MLKEMs), intermediate config, gitrev=1b22dc6
# https://configurator.tlsref.org/#server=apache&version=2.4.52&config=intermediate&openssl=3.0.2&guideline=6.0
SSLProtocol -all +TLSv1.2 +TLSv1.3
SSLOpenSSLConfCmd Curves X25519:prime256v1:secp384r1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLCipherSuite TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
{%- endif %}
SSLHonorCipherOrder off
SSLSessionTickets off
</IfModule>
15 changes: 0 additions & 15 deletions salt/apache/init.sls
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,10 @@
{{ unset_firewall('PUBLIC_HTTPS') }}
{% endif %}

# ondrej/apache2 is still needed on Ubuntu 20.04 for MDContactEmail.
# https://github.com/icing/mod_md/issues/203
apache2:
{% if grains.osmajorrelease in ('18', '20') %}
pkgrepo.managed:
- ppa: ondrej/apache2
{% endif %}
pkg.installed:
- pkgs:
- apache2
{% if grains.osmajorrelease in ('18', '20') %}
# Avoid "AH01882: Init: this version of mod_ssl was compiled against a newer library (OpenSSL 1.1.1g 21 Apr 2020,
# version currently loaded is OpenSSL 1.1.1 11 Sep 2018) - may result in undefined or erroneous behavior"
# https://github.com/open-contracting/deploy/issues/66#issuecomment-742898193
- libssl1.1
- openssl
- require:
- pkgrepo: apache2
{% endif %}
service.running:
- name: apache2
- enable: True
Expand Down
2 changes: 0 additions & 2 deletions salt/core/apt/init.sls
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ needrestart:
pkg.removed:
- name: needrestart

# https://www.phusionpassenger.com/library/install/apache/install/oss/bionic/
# gnupg depends on dirmngr. gnupg2 is a dummy package for gnupg.
secure ppa:
pkg.installed:
- pkgs:
Expand Down
4 changes: 4 additions & 0 deletions salt/core/fail2ban/init.sls
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ fail2ban:
[Definition]
failregex = ^<HOST> .* ".*" 404
ignoreregex =
- require:
- pkg: apache2
- require_in:
- file: /etc/fail2ban/jail.local
- watch_in:
Expand All @@ -37,6 +39,8 @@ fail2ban:
[Definition]
failregex = ^<HOST> .* FATAL: password authentication failed for user ".*"$
ignoreregex =
- require:
- pkg: postgresql
- require_in:
- file: /etc/fail2ban/jail.local
- watch_in:
Expand Down
4 changes: 2 additions & 2 deletions salt/core/firewall/files/firewall.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ fi

echo_verbose "Get iptables location"
case "${ID}_${VERSION_ID}" in
ubuntu_24.04 | ubuntu_22.04 | ubuntu_20.04 | ubuntu_18.04 | debian_10 | debian_9 | debian_8)
ubuntu_26.04 | ubuntu_24.04 | ubuntu_22.04 | debian_13 | debian_12)
IPTABLESSAVLOC=/etc/iptables/rules.v4
IP6TABLESSAVLOC=/etc/iptables/rules.v6
;;
centos_7 | redhat-derivative_)
redhat-derivative_)
IPTABLESSAVLOC=/etc/sysconfig/iptables
IP6TABLESSAVLOC=/etc/sysconfig/ip6tables
;;
Expand Down
4 changes: 2 additions & 2 deletions salt/core/firewall/files/firewall_reset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ fi

echo_verbose "Get iptables location"
case "${ID}_${VERSION_ID}" in
ubuntu_22.04 | ubuntu_20.04 | ubuntu_18.04 | debian_10 | debian_9 | debian_8)
ubuntu_26.04 | ubuntu_24.04 | ubuntu_22.04 | debian_13 | debian_12)
IPTABLESSAVLOC=/etc/iptables/rules.v4
IP6TABLESSAVLOC=/etc/iptables/rules.v6
;;
centos_7 | redhat-derivative_)
redhat-derivative_)
IPTABLESSAVLOC=/etc/sysconfig/iptables
IP6TABLESSAVLOC=/etc/sysconfig/ip6tables
;;
Expand Down
3 changes: 3 additions & 0 deletions salt/core/firewall/init.sls
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ iptables-persistent:
save iptables rules:
cmd.run:
- name: /home/sysadmin-tools/bin/firewall.sh
- success_retcodes:
Comment thread
RobHooper marked this conversation as resolved.
- 0
- 3 # Docker install detected, exiting early.
- onchanges:
- file: /home/sysadmin-tools/firewall-settings.local
- file: /home/sysadmin-tools/bin/firewall.sh
Expand Down
4 changes: 4 additions & 0 deletions salt/core/mail.sls
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ postfix:
smtp_sasl_auth_enable: "yes"
smtp_sasl_security_options: "noanonymous"
smtp_sasl_password_maps: "hash:/etc/postfix/sasl_passwd"
{% if grains.osmajorrelease|int < 26 %}
# Deprecated in Postfix 3.9, instead specify 'smtp_tls_security_level'
smtp_use_tls: "yes"
{% endif %}
smtp_tls_security_level: "may"
smtp_tls_note_starttls_offer: "yes"
{%- if "relay_address" in pillar.smtp %}
smtp_generic_maps: "hash:/etc/postfix/generic"
Expand Down
3 changes: 3 additions & 0 deletions salt/core/ntp/files/ntp-pools.sources
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{%- for source, entry in pillar.nts | items %}
pool {{ source }} {{ entry.context | default("iburst maxsources 1 nts prefer") }}
{%- endfor %}
31 changes: 25 additions & 6 deletions salt/core/systemd/ntp.sls → salt/core/ntp/init.sls
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
# Configure an SNTP service.
{% if grains.osmajorrelease|int >= 26 %}
chrony:
service.running:
- name: chrony

chrony-reload:
cmd.wait:
- name: chronyc reload sources

/etc/chrony/sources.d/ntp-pools.sources:
Comment thread
RobHooper marked this conversation as resolved.
file.managed:
- source: salt://core/ntp/files/ntp-pools.sources
- template: jinja
- watch_in:
- cmd: chrony-reload

/etc/chrony/sources.d/ubuntu-ntp-pools.sources:
file.comment:
- regex: "^pool "
- backup: False
- watch_in:
- cmd: chrony-reload
{% else %}
systemd-timesyncd:
{% if grains['osrelease'] >= '20.04' %}
# timesyncd is built into systemd on older Ubuntu releases.
pkg.installed:
- name: systemd-timesyncd
{% endif %}
service.running:
- name: systemd-timesyncd
- enable: True
{% if grains['osrelease'] >= '20.04' %}
- require:
- pkg: systemd-timesyncd
{% endif %}

/etc/systemd/timesyncd.conf.d/customization.conf:
file.managed:
- source: salt://core/systemd/files/timesyncd.conf
- source: salt://core/ntp/files/timesyncd.conf
- template: jinja
- makedirs: True
- watch_in:
Expand All @@ -27,6 +45,7 @@ systemd-timesyncd:
- backup: False
- watch_in:
- service: systemd-timesyncd
{% endif %}

set timezone to utc:
timezone.system:
Expand Down
5 changes: 5 additions & 0 deletions salt/core/sshd/files/customization.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{#-
We set both PermitRootLogin and PasswordAuthentication for two reasons:
- PermitRootLogin adds a layer of security in case PasswordAuthentication is toggled on.
- While PermitRootLogin is set to "no" or "without-password", we can monitor it with our intrusion detection software.
-#}
PasswordAuthentication no
PermitRootLogin without-password
X11Forwarding no
25 changes: 1 addition & 24 deletions salt/core/sshd/init.sls
Original file line number Diff line number Diff line change
@@ -1,34 +1,11 @@
# We'll only be using SSH key authentication.
{% if grains['osrelease'] >= '20.04' %}
/etc/ssh/sshd_config.d/customization.conf:
file.managed:
- source: salt://core/sshd/files/customization.conf
- template: jinja
- watch_in:
- service: ssh_service

{% else %}
# We set both PermitRootLogin and PasswordAuthentication for two reasons:
#
# - PermitRootLogin adds a layer of security in case PasswordAuthentication is toggled on.
# - While PermitRootLogin is set to "no" or "without-password", we can monitor it with our intrusion detection software.
harden ssh configuration:
file.keyvalue:
- name: /etc/ssh/sshd_config
- key_values:
# Disable password authentication.
PasswordAuthentication: 'no'
# Force root logins with SSH keys.
PermitRootLogin: without-password
# Disable X11 forwarding.
X11Forwarding: 'no'
- separator: ' '
- uncomment: '# '
- key_ignore_case: True
- append_if_not_found: True
- watch_in:
- service: ssh_service
{% endif %}

# Restart the SSH service if the config changes.
ssh_service:
service.running:
Expand Down
4 changes: 0 additions & 4 deletions salt/docker/init.sls
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
docker:
pkgrepo.managed:
- humanname: Docker Official Repository
{% if grains.osmajorrelease|string in ('18', '20') %}
- name: deb [arch={{ grains.osarch }}] https://download.docker.com/{{ grains.kernel|lower }}/{{ grains.os|lower }} {{ grains.oscodename }} stable
{% else %}
- name: deb [arch={{ grains.osarch }} signed-by=/usr/share/keyrings/docker-keyring.gpg] https://download.docker.com/{{ grains.kernel|lower }}/{{ grains.os|lower }} {{ grains.oscodename }} stable
- aptkey: False
{% endif %}
- dist: {{ grains.oscodename }}
- file: /etc/apt/sources.list.d/docker.list
- key_url: https://download.docker.com/{{ grains.kernel|lower }}/{{ grains.os|lower }}/gpg
Expand Down
8 changes: 7 additions & 1 deletion salt/mysql/init.sls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set mysql_version = pillar.mysql.version|default('8.0')|quote %}
{% set mysql_version = pillar.mysql.version|default('8.4')|quote %}

# https://docs.saltproject.io/en/latest/ref/states/all/salt.states.mysql_database.html
mysql dependencies:
Expand All @@ -13,8 +13,14 @@ percona-release:
- sources:
- percona-release: https://repo.percona.com/apt/percona-release_latest.{{ salt['grains.get']('lsb_distrib_codename') }}_all.deb
cmd.run:
{% if pillar.mysql.version == '8.0' %}
# Legacy naming format
- name: percona-release setup ps{{ mysql_version|replace('.', '') }}
- creates: /etc/apt/sources.list.d/percona-ps-{{ mysql_version|replace('.', '') }}-release.list
{% else %}
- name: percona-release setup ps{{ mysql_version|replace('.', '') }}-lts --scheme https
- creates: /etc/apt/sources.list.d/percona-ps-{{ mysql_version|replace('.', '') }}-lts-release.list
{% endif %}
- require:
- pkg: percona-release

Expand Down
2 changes: 1 addition & 1 deletion salt/php-fpm/init.sls
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% set php_version = pillar.php.version|default('8.1')|quote %}
{% set php_version = pillar.php.version|default('8.5')|quote %}

include:
- apache.modules.proxy_fcgi
Expand Down
4 changes: 0 additions & 4 deletions salt/postgres/init.sls
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,8 @@ pgbadger:
postgresql:
pkgrepo.managed:
- humanname: PostgreSQL Official Repository
{% if grains.osmajorrelease|string in ('18', '20') %}
- name: deb https://apt.postgresql.org/pub/repos/apt {{ grains.oscodename }}-pgdg main
{% else %}
- name: deb [signed-by=/usr/share/keyrings/postgresql-keyring.gpg] https://apt.postgresql.org/pub/repos/apt {{ grains.oscodename }}-pgdg main
- aptkey: False
{% endif %}
- dist: {{ grains.oscodename }}-pgdg
- file: /etc/apt/sources.list.d/psql.list
- key_url: https://www.postgresql.org/media/keys/ACCC4CF8.asc
Expand Down
2 changes: 1 addition & 1 deletion salt/top.sls
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ base:
- core.mail
- core.motd
- core.network
- core.ntp
- core.reboot
- core.rsyslog
- core.sshd
- core.swap
- core.sysctl
- core.systemd.logind
- core.systemd.ntp

'cms':
- cms
Expand Down
Loading