4.21.3
1090
app/docs/api.md
Normal file
BIN
app/docs/archi.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
app/docs/banner.png
Normal file
After Width: | Height: | Size: 114 KiB |
15
app/docs/build-image.md
Normal file
@ -0,0 +1,15 @@
|
||||
To build a multi-architecture image, you need to use `buildx`.
|
||||
|
||||
Here's the command to build and push the images from a Mac M1:
|
||||
|
||||
1) First create a new buildx environment (or context). This is only necessary for the first time.
|
||||
|
||||
```bash
|
||||
docker buildx create --use
|
||||
```
|
||||
|
||||
2) Build and push the image. Replace `simplelogin/name:tag` by the correct docker image name and tag.
|
||||
|
||||
```bash
|
||||
docker buildx build --platform linux/amd64,linux/arm64 --push -t simplelogin/name:tag
|
||||
```
|
10
app/docs/code-structure.md
Normal file
@ -0,0 +1,10 @@
|
||||
# TODO
|
||||
|
||||
`local_data/`: contain files used only locally. In deployment, these files should be replaced.
|
||||
- jwtRS256.key: generated using
|
||||
|
||||
```bash
|
||||
ssh-keygen -t rsa -b 4096 -m PEM -f jwtRS256.key
|
||||
# Don't add passphrase
|
||||
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub
|
||||
```
|
BIN
app/docs/custom-alias.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/docs/diagram.png
Normal file
After Width: | Height: | Size: 55 KiB |
51
app/docs/enforce-spf.md
Normal file
@ -0,0 +1,51 @@
|
||||
Some email services like Gmail, Proton Mail, etc don't have a strict SPF record (`-all`) to support the "classic" email forwarding
|
||||
that is usually used for group mailing list. In this scenario, an email is sent to a group is forwarded as-is,
|
||||
breaking therefore the SPF.
|
||||
|
||||
A malicious hacker could use this security fail to impersonate your alias via the reverse-alias. This rarely happens
|
||||
as the reverse-alias is generated randomly and is unique for each sender.
|
||||
|
||||
However if you want to prevent this kind of attack, you can enforce the SPF policy even if your mailbox uses a "soft" policy.
|
||||
|
||||
1) Install `postfix-pcre`
|
||||
|
||||
```bash
|
||||
apt install -y postfix-pcre
|
||||
```
|
||||
|
||||
2) Add `/etc/postfix/body_checks.pcre` file with the following content
|
||||
|
||||
```
|
||||
/^X-SimpleLogin-Client-IP:/ IGNORE
|
||||
```
|
||||
|
||||
3) Add `/etc/postfix/client_headers.pcre` with the following content
|
||||
|
||||
```
|
||||
/^([0-9a-f:.]+)$/ prepend X-SimpleLogin-Client-IP: $1
|
||||
```
|
||||
|
||||
4) Add the following lines to your Postfix config file at `/etc/postfix/main.cf`
|
||||
|
||||
```
|
||||
body_checks = pcre:/etc/postfix/body_checks.pcre
|
||||
smtpd_client_restrictions = pcre:/etc/postfix/client_headers.pcre
|
||||
```
|
||||
|
||||
5) Enable `ENFORCE_SPF` in your SimpleLogin config file
|
||||
|
||||
```
|
||||
ENFORCE_SPF=true
|
||||
```
|
||||
|
||||
6) Restart Postfix
|
||||
|
||||
```bash
|
||||
systemctl restart postfix
|
||||
```
|
||||
|
||||
7) Restart SimpleLogin mail handler
|
||||
|
||||
```bash
|
||||
sudo docker restart sl-email
|
||||
```
|
200
app/docs/gmail-relay.md
Normal file
@ -0,0 +1,200 @@
|
||||
# Using Gmail as SMTP relay to send email from SimpleLogin
|
||||
|
||||
###### port 25 blocked by ISP...?
|
||||
|
||||
> you can use postfix with a Gmail SMTP relay... So Postfix will send on port 587.
|
||||
|
||||
## How to:
|
||||
|
||||
- create a Gmail account
|
||||
- set MFA
|
||||
- create an app password
|
||||
|
||||
- update firewall's rules for port 587
|
||||
|
||||
- update Postfix conf:
|
||||
|
||||
=> nano /etc/postfix/master.cf
|
||||
```
|
||||
...
|
||||
# ==========================================================================
|
||||
# service type private unpriv chroot wakeup maxproc command + args
|
||||
# (yes) (yes) (no) (never) (100)
|
||||
# ==========================================================================
|
||||
smtp inet n - y - - smtpd
|
||||
#smtp inet n - y - 1 postscreen
|
||||
#smtpd pass - - y - - smtpd
|
||||
#dnsblog unix - - y - 0 dnsblog
|
||||
#tlsproxy unix - - y - 0 tlsproxy
|
||||
submission inet n - y - - smtpd
|
||||
-o syslog_name=postfix/submission
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
-o smtpd_tls_auth_only=yes
|
||||
# -o smtpd_reject_unlisted_recipient=no
|
||||
# -o smtpd_client_restrictions=$mua_client_restrictions
|
||||
# -o smtpd_helo_restrictions=$mua_helo_restrictions
|
||||
...
|
||||
```
|
||||
=> nano /etc/postfix/sasl_passwd
|
||||
```
|
||||
[smtp.gmail.com]:587 email_created@gmail.com:app_password_created
|
||||
```
|
||||
=> postmap /etc/postfix/sasl_passwd
|
||||
|
||||
=> chmod 600 /etc/postfix/sasl_passwd
|
||||
|
||||
=> nano /etc/postfix/main.cf
|
||||
```
|
||||
# POSTFIX config file, adapted for SimpleLogin
|
||||
smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
|
||||
biff = no
|
||||
|
||||
# appending .domain is the MUA's job.
|
||||
append_dot_mydomain = no
|
||||
|
||||
# Uncomment the next line to generate "delayed mail" warnings
|
||||
#delay_warning_time = 4h
|
||||
|
||||
readme_directory = no
|
||||
|
||||
# See http://www.postfix.org/COMPATIBILITY_README.html -- default to 2 on
|
||||
# fresh installs.
|
||||
compatibility_level = 2
|
||||
|
||||
# TLS parameters
|
||||
smtpd_tls_cert_file=/etc/letsencrypt/live/app.mydomain.com/fullchain.pem
|
||||
smtpd_tls_key_file=/etc/letsencrypt/live/app.mydomain.com/privkey.pem
|
||||
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
|
||||
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
|
||||
smtp_tls_security_level = may
|
||||
smtpd_tls_security_level = may
|
||||
|
||||
# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
|
||||
# information on enabling SSL in the smtp client.
|
||||
|
||||
alias_maps = hash:/etc/aliases
|
||||
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 10.0.0.0/24
|
||||
|
||||
# Set your domain here
|
||||
mydestination = localhost.localdomain, localhost
|
||||
myhostname = app.mydomain.com
|
||||
mydomain = mydomain.com
|
||||
myorigin = /etc/mailname
|
||||
relay_domains = pgsql:/etc/postfix/pgsql-relay-domains.cf
|
||||
transport_maps = pgsql:/etc/postfix/pgsql-transport-maps.cf
|
||||
|
||||
# HELO restrictions
|
||||
smtpd_delay_reject = yes
|
||||
smtpd_helo_required = yes
|
||||
smtpd_helo_restrictions =
|
||||
permit_mynetworks,
|
||||
reject_non_fqdn_helo_hostname,
|
||||
reject_invalid_helo_hostname,
|
||||
permit
|
||||
|
||||
# Sender restrictions:
|
||||
smtpd_sender_restrictions =
|
||||
permit_mynetworks,
|
||||
reject_non_fqdn_sender,
|
||||
reject_unknown_sender_domain,
|
||||
permit
|
||||
|
||||
# Recipient restrictions:
|
||||
smtpd_recipient_restrictions =
|
||||
reject_unauth_pipelining,
|
||||
reject_non_fqdn_recipient,
|
||||
reject_unknown_recipient_domain,
|
||||
permit_mynetworks,
|
||||
reject_unauth_destination,
|
||||
reject_rbl_client zen.spamhaus.org,
|
||||
reject_rbl_client bl.spamcop.net,
|
||||
permit
|
||||
|
||||
# Enfore SPF
|
||||
body_checks = pcre:/etc/postfix/body_checks.pcre
|
||||
smtpd_client_restrictions = pcre:/etc/postfix/client_headers.pcre
|
||||
|
||||
# Postfix conf
|
||||
mailbox_size_limit = 10000000000
|
||||
recipient_delimiter = -
|
||||
inet_interfaces = all
|
||||
inet_protocols = ipv4
|
||||
|
||||
# Relay Gmail
|
||||
smtp_sasl_auth_enable = yes
|
||||
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
||||
smtp_sasl_security_options = noanonymous
|
||||
smtp_sasl_tls_security_options = noanonymous
|
||||
header_size_limit = 4096000
|
||||
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
|
||||
relayhost = [smtp.gmail.com]:587
|
||||
```
|
||||
>cat /etc/hosts
|
||||
>
|
||||
>127.0.0.1 localhost.localdomain localhost
|
||||
|
||||
- restart Postfix:
|
||||
|
||||
=> systemctl reload postfix
|
||||
|
||||
=> service postfix restart
|
||||
|
||||
- update SimpleLogin conf:
|
||||
|
||||
=> nano /simplelogin.env
|
||||
```
|
||||
# WebApp URL
|
||||
URL=http://app.mydomain.com
|
||||
|
||||
# domain used to create alias
|
||||
EMAIL_DOMAIN=mydomaine.com
|
||||
|
||||
# transactional email is sent from this email address
|
||||
SUPPORT_EMAIL=support@mydomain.com
|
||||
|
||||
# custom domain needs to point to these MX servers
|
||||
EMAIL_SERVERS_WITH_PRIORITY=[(10, "app.mydomain.com.")]
|
||||
|
||||
# By default, new aliases must end with ".{random_word}". This is to avoid a person taking all "nice" aliases.
|
||||
# this option doesn't make sense in self-hosted. Set this variable to disable this option.
|
||||
DISABLE_ALIAS_SUFFIX=1
|
||||
|
||||
# the DKIM private key used to compute DKIM-Signature
|
||||
DKIM_PRIVATE_KEY_PATH=/dkim.key
|
||||
|
||||
# DB Connection
|
||||
DB_URI=postgresql://mysqluser:mysqlpassword@sl-db:5432/simplelogin
|
||||
|
||||
FLASK_SECRET=SomeThing_Secret
|
||||
|
||||
GNUPGHOME=/sl/pgp
|
||||
|
||||
LOCAL_FILE_UPLOAD=1
|
||||
|
||||
# Postfix 587 TLS
|
||||
POSTFIX_PORT=587
|
||||
|
||||
POSTFIX_SUBMISSION_TLS=true
|
||||
|
||||
# Enforce SPF
|
||||
ENFORCE_SPF=true
|
||||
|
||||
```
|
||||
- restart SL-Mail:
|
||||
|
||||
=> docker restart sl-email
|
||||
|
||||
=> reboot
|
||||
|
||||
> for debug:
|
||||
>
|
||||
> view system logs => tail -f /var/log/syslog
|
||||
>
|
||||
> view postfix logs => tail -f /var/log/mail.log
|
||||
>
|
||||
> view postfix queue => mailq
|
||||
>
|
||||
> delete postfix queue => postsuper -d ALL
|
||||
|
||||
;-)
|
BIN
app/docs/hero.png
Normal file
After Width: | Height: | Size: 285 KiB |
49
app/docs/hero.svg
Normal file
@ -0,0 +1,49 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1105" height="1131" viewBox="0 0 1105 1131">
|
||||
<defs>
|
||||
<linearGradient id="linear-gradient" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#e3156a"/>
|
||||
<stop offset="1" stop-color="#91187f"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip-Artboard_3">
|
||||
<rect width="1105" height="1131"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="Artboard_3" data-name="Artboard – 3" clip-path="url(#clip-Artboard_3)">
|
||||
<rect width="1105" height="1131" fill="#fff"/>
|
||||
<path id="Icon_simple-groupon" data-name="Icon simple-groupon" d="M7.6,46.6A26.694,26.694,0,0,0,27.527,55,27.933,27.933,0,0,0,50.394,43.168,26.235,26.235,0,0,0,55,27.688c0-1.109-.073-2.305-.144-3.5H24.28V34.748H39.6A13.689,13.689,0,0,1,27.527,41.9c-7.4,0-14.036-6.472-14.036-14.889A13.963,13.963,0,0,1,27.527,13.1c4.226,0,7.689,1.716,11.025,5.131H53.494C49.2,6.919,39.151,0,27.69,0A27.308,27.308,0,0,0,8.142,7.812,26.319,26.319,0,0,0,0,26.936,27.257,27.257,0,0,0,7.6,46.6Z" transform="translate(181 141)" fill="rgba(66,150,56,0.69)"/>
|
||||
<text id="groupon_alias.com" data-name="groupon@alias.com" transform="translate(91.809 596.283)" fill="#c11672" font-size="26" font-family="HelveticaNeue, Helvetica Neue" opacity="0.997"><tspan x="0" y="0">groupon@alias.com</tspan></text>
|
||||
<text id="meetup_alias.com" data-name="meetup@alias.com" transform="translate(800.967 594.607)" fill="#b91674" font-size="26" font-family="HelveticaNeue, Helvetica Neue" opacity="0.997"><tspan x="0" y="0">meetup@alias.com</tspan></text>
|
||||
<text id="facebook_alias.com" data-name="facebook@alias.com" transform="translate(444.654 594.565)" fill="#bc1673" font-size="26" font-family="HelveticaNeue, Helvetica Neue" opacity="0.997"><tspan x="0" y="0">facebook@alias.com</tspan></text>
|
||||
<path id="Icon_simple-meetup" data-name="Icon simple-meetup" d="M54.948,44.712c-.7-4.425-8.878-1.017-9.386-5.864-.717-6.87,9.51-21.676,8.7-27.435C53.546,6.245,50.044,5.157,47.01,5.1c-2.942-.046-3.719.417-4.716,1A1.772,1.772,0,0,1,39.746,6c-.765-.729-1.276-1.228-2.074-1.877a4.388,4.388,0,0,0-2.166-.905,7.109,7.109,0,0,0-3.419.383,9.429,9.429,0,0,0-2.351,1.716c-.74.649-2.628,2.745-4.379,1.968-.768-.332-3.341-1.618-5.207-2.418-3.582-1.551-8.759.962-10.624,4.276-2.78,4.925-8.25,24.3-9.084,26.846-1.854,5.734,2.365,10.4,8.041,10.138,2.411-.117,4.01-.985,5.527-3.754.88-1.588,9.118-23.115,9.735-24.16a2.7,2.7,0,0,1,3.185-1.089,2.916,2.916,0,0,1,1.331,3.256c-.312,2.051-6.116,15.191-6.35,16.671-.371,2.528.823,3.928,3.453,4.065,1.8.094,3.591-.543,5-3.231.8-1.494,9.966-19.859,10.775-21.087.894-1.343,1.611-1.785,2.528-1.737.708.034,1.831.22,1.554,2.328-.28,2.074-7.661,15.537-8.424,18.839a9.752,9.752,0,0,0,5.365,10.835c2.548,1.251,13.681,3.382,12.78-2.353Z" transform="translate(902 139.845)" fill="rgba(237,65,65,0.81)"/>
|
||||
<path id="Icon_awesome-facebook-square" data-name="Icon awesome-facebook-square" d="M49.107,2.25H5.893A5.893,5.893,0,0,0,0,8.143V51.357A5.893,5.893,0,0,0,5.893,57.25h16.85v-18.7H15.008v-8.8h7.734V23.042c0-7.63,4.542-11.845,11.5-11.845a46.856,46.856,0,0,1,6.816.594V19.28H37.22c-3.782,0-4.962,2.347-4.962,4.755V29.75H40.7l-1.35,8.8H32.257v18.7h16.85A5.893,5.893,0,0,0,55,51.357V8.143A5.893,5.893,0,0,0,49.107,2.25Z" transform="translate(550 136.75)" fill="rgba(78,85,165,0.79)"/>
|
||||
<path id="Icon_awesome-toggle-on" data-name="Icon awesome-toggle-on" d="M30,4.5H15a15,15,0,1,0,0,30H30a15,15,0,1,0,0-30Zm0,25a10,10,0,1,1,10-10A9.994,9.994,0,0,1,30,29.5Z" transform="translate(251 512.5)" fill="#aa1778"/>
|
||||
<path id="Icon_awesome-toggle-on-2" data-name="Icon awesome-toggle-on" d="M30,4.5H15a15,15,0,1,0,0,30H30a15,15,0,1,0,0-30Zm0,25a10,10,0,1,1,10-10A9.994,9.994,0,0,1,30,29.5Z" transform="translate(965 503.5)" fill="#b91674"/>
|
||||
<path id="Icon_awesome-toggle-off" data-name="Icon awesome-toggle-off" d="M30,4.5H15a15,15,0,1,0,0,30H30a15,15,0,1,0,0-30ZM5,19.5a10,10,0,1,1,10,10A9.995,9.995,0,0,1,5,19.5Zm25,10H26.179a14.994,14.994,0,0,0,0-20H30a10,10,0,0,1,0,20Z" transform="translate(625 511.5)" fill="#c61671"/>
|
||||
<path id="Icon_material-mail-outline" data-name="Icon material-mail-outline" d="M57,6H9a5.992,5.992,0,0,0-5.97,6L3,48a6.018,6.018,0,0,0,6,6H57a6.018,6.018,0,0,0,6-6V12A6.018,6.018,0,0,0,57,6Zm0,42H9V18L33,33,57,18ZM33,27,9,12H57Z" transform="translate(173 502)" fill="#7bb674"/>
|
||||
<path id="Icon_material-mail-outline-2" data-name="Icon material-mail-outline" d="M57,6H9a5.992,5.992,0,0,0-5.97,6L3,48a6.018,6.018,0,0,0,6,6H57a6.018,6.018,0,0,0,6-6V12A6.018,6.018,0,0,0,57,6Zm0,42H9V18L33,33,57,18ZM33,27,9,12H57Z" transform="translate(547 499)" fill="#7379b8"/>
|
||||
<path id="Icon_material-mail-outline-3" data-name="Icon material-mail-outline" d="M57,6H9a5.992,5.992,0,0,0-5.97,6L3,48a6.018,6.018,0,0,0,6,6H57a6.018,6.018,0,0,0,6-6V12A6.018,6.018,0,0,0,57,6Zm0,42H9V18L33,33,57,18ZM33,27,9,12H57Z" transform="translate(887 499)" fill="#f06565"/>
|
||||
<line id="Line_1" data-name="Line 1" x1="1" y2="258" transform="translate(205.5 218.5)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<line id="Line_4" data-name="Line 4" x1="1" y2="258" transform="translate(931.5 204.5)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<line id="Line_2" data-name="Line 2" y2="85" transform="translate(580.5 217.5)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<line id="Line_3" data-name="Line 3" y2="108" transform="translate(580.5 361.5)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<path id="Path_186" data-name="Path 186" d="M-164.529,1669.5l16.008,14.3,17.483-14.3" transform="translate(729 -1202)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<path id="Path_191" data-name="Path 191" d="M-164.529,1669.5l16.008,14.3,17.483-14.3" transform="translate(354 -1201)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<path id="Path_192" data-name="Path 192" d="M-164.529,1669.5l16.008,14.3,17.483-14.3" transform="translate(1080 -1215)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<path id="Icon_ionic-md-paper-plane" data-name="Icon ionic-md-paper-plane" d="M3.375,27.487l12.862,4.825,1.6,16.064,8.037-11.25,11.25,11.25,11.25-45Zm31.9,13.63-8.968-9.032L38.737,14.625,19.125,29.531l-7.431-2.683,31.478-16.9Z" transform="matrix(-0.174, 0.985, -0.985, -0.174, 203.577, 332.524)" fill="#c11672"/>
|
||||
<path id="Icon_ionic-md-paper-plane-2" data-name="Icon ionic-md-paper-plane" d="M3.375,27.487l12.862,4.825,1.6,16.064,8.037-11.25,11.25,11.25,11.25-45Zm31.9,13.63-8.968-9.032L38.737,14.625,19.125,29.531l-7.431-2.683,31.478-16.9Z" transform="matrix(-0.174, 0.985, -0.985, -0.174, 929.577, 318.524)" fill="#c11672"/>
|
||||
<g id="Icon_ionic-md-mail-unread" data-name="Icon ionic-md-mail-unread" transform="translate(529.75 896.5)">
|
||||
<path id="Path_187" data-name="Path 187" d="M34.875,9a4.5,4.5,0,1,1-4.5-4.5,4.5,4.5,0,0,1,4.5,4.5Z" transform="translate(57.375)" fill="#af1677"/>
|
||||
<path id="Path_188" data-name="Path 188" d="M71.852,30.254,46.681,47.139,11.771,23.727V15.205l34.91,23.411L66.735,25.164A18.039,18.039,0,0,1,66.5,5.625H10.72a8.517,8.517,0,0,0-8.47,8.522V67.376A8.517,8.517,0,0,0,10.72,75.9H82.662a8.517,8.517,0,0,0,8.47-8.522V30.393a17.762,17.762,0,0,1-19.28-.14Z" transform="translate(0 0)" fill="#af1677"/>
|
||||
</g>
|
||||
<path id="Path_189" data-name="Path 189" d="M-147.165,1816s-43.6,110.247,31.553,178.6,104.424,7.328,185.53,15.373S171,2081.49,171,2081.49" transform="translate(353 -1200)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<path id="Path_190" data-name="Path 190" d="M152,2079.774l22.535,5.764v-20.9" transform="translate(355.277 -1200)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 4"/>
|
||||
<text id="X" transform="translate(567 352)" fill="#b11777" font-size="44" font-family="HelveticaNeue, Helvetica Neue"><tspan x="0" y="0">X</tspan></text>
|
||||
<text id="my-real-email_example.com" data-name="my-real-email@example.com" transform="translate(397 1006)" fill="#ae0721" font-size="30" font-family="HelveticaNeue, Helvetica Neue"><tspan x="0" y="0">my-real-email@example.com</tspan></text>
|
||||
<path id="Icon_map-locksmith" data-name="Icon map-locksmith" d="M31.075,15.12H29.52V8.9c0-4.088-4.1-8.185-8.189-8.185H14.5C10.418.72,6.48,4.817,6.48,8.9V15.12H4.759a1.544,1.544,0,0,0-1.159,1.2v18.33c0,.431.672.635,1.159.635H31.075c.489,0,1.325-.2,1.325-.635V16.315a1.76,1.76,0,0,0-1.325-1.2ZM21.393,32.4H14.445L15.9,25.224a3.723,3.723,0,0,1-1.458-2.956,3.527,3.527,0,0,1,3.474-3.524,3.428,3.428,0,0,1,3.475,3.406,4,4,0,0,1-1.457,3.094ZM24.48,15.12H11.52V8.9A2.944,2.944,0,0,1,14.574,5.76h6.688A3.076,3.076,0,0,1,24.48,8.9Z" transform="translate(285.93 767)" fill="url(#linear-gradient)"/>
|
||||
<path id="Icon_map-locksmith-2" data-name="Icon map-locksmith" d="M31.075,15.12H29.52V8.9c0-4.088-4.1-8.185-8.189-8.185H14.5C10.418.72,6.48,4.817,6.48,8.9V15.12H4.759a1.544,1.544,0,0,0-1.159,1.2v18.33c0,.431.672.635,1.159.635H31.075c.489,0,1.325-.2,1.325-.635V16.315a1.76,1.76,0,0,0-1.325-1.2ZM21.393,32.4H14.445L15.9,25.224a3.723,3.723,0,0,1-1.458-2.956,3.527,3.527,0,0,1,3.474-3.524,3.428,3.428,0,0,1,3.475,3.406,4,4,0,0,1-1.457,3.094ZM24.48,15.12H11.52V8.9A2.944,2.944,0,0,1,14.574,5.76h6.688A3.076,3.076,0,0,1,24.48,8.9Z" transform="translate(713.93 709)" fill="url(#linear-gradient)"/>
|
||||
<path id="Path_195" data-name="Path 195" d="M852.538,1776.159s-40.43,11.784-54.916,60,0,81.47,0,81.47,11.734,48.231,48.454,32.742,6.461-52.778,6.461-52.778-32.971-17.76-73.978,14.531-92.788,152.565-92.788,152.565" transform="translate(-37.825 -1155.685)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 6"/>
|
||||
<path id="Path_196" data-name="Path 196" d="M294.5,2009.748l-2.011,17.9,15.542-6.695" transform="translate(351 -1114)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 4"/>
|
||||
<path id="Path_197" data-name="Path 197" d="M-159.743,1740.307l15.2-15.786,7.495,20.667" transform="translate(354 -1119)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 4"/>
|
||||
<path id="Path_198" data-name="Path 198" d="M453.9,1730.937l19.345,3.03-10.607,18.592" transform="translate(353 -1119)" fill="none" stroke="#707070" stroke-width="3" stroke-dasharray="4 4"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
57
app/docs/oauth.md
Normal file
@ -0,0 +1,57 @@
|
||||
## OAuth
|
||||
|
||||
SL currently supports code and implicit flow.
|
||||
|
||||
#### Code flow
|
||||
|
||||
To trigger the code flow locally, you can go to the [following url](http://localhost:7777/oauth/authorize?client_id=client-id&state=123456&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A7000%2Fcallback&state=random_string) after running `python server.py`:
|
||||
|
||||
|
||||
You should see the authorization page where user is asked for permission to share their data. Once user approves, user is redirected to this url with an `authorization code`: `http://localhost:7000/callback?state=123456&code=the_code`
|
||||
|
||||
Next, exchange the code to get the token with `{code}` replaced by the code obtained in previous step. The `http` tool used here is [httpie](https://httpie.org)
|
||||
|
||||
```
|
||||
http -f -a client-id:client-secret http://localhost:7777/oauth/token grant_type=authorization_code code={code}
|
||||
```
|
||||
|
||||
This should return an `access token` that allows to get user info via the following command. Again, `http` is used.
|
||||
|
||||
```
|
||||
http http://localhost:7777/oauth/user_info 'Authorization:Bearer {token}'
|
||||
```
|
||||
|
||||
#### Implicit flow
|
||||
|
||||
Similar to code flow, except for the the `access token` which we we get back with the redirection.
|
||||
For implicit flow, you can use [this url](http://localhost:7777/oauth/authorize?client_id=client-id&state=123456&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A7000%2Fcallback&state=random_string)
|
||||
|
||||
#### OpenID and OAuth2 response_type & scope
|
||||
|
||||
According to the sharing web blog titled [Diagrams of All The OpenID Connect Flows](https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660), we should pay attention to:
|
||||
|
||||
- `response_type` can be either `code, token, id_token` or any combination of those attributes.
|
||||
- `scope` might contain `openid`
|
||||
|
||||
Below are the potential combinations that are taken into account in SL until now:
|
||||
|
||||
```
|
||||
response_type=code
|
||||
scope:
|
||||
with `openid` in scope, return `id_token` at /token: OK
|
||||
without: OK
|
||||
|
||||
response_type=token
|
||||
scope:
|
||||
with and without `openid`, nothing to do: OK
|
||||
|
||||
response_type=id_token
|
||||
return `id_token` in /authorization endpoint
|
||||
|
||||
response_type=id_token token
|
||||
return `id_token` in addition to `access_token` in /authorization endpoint
|
||||
|
||||
response_type=id_token code
|
||||
return `id_token` in addition to `authorization_code` in /authorization endpoint
|
||||
|
||||
```
|
BIN
app/docs/one-click-alias.gif
Normal file
After Width: | Height: | Size: 1.4 MiB |
BIN
app/docs/postfix-installation.png
Normal file
After Width: | Height: | Size: 59 KiB |
BIN
app/docs/postfix-installation2.png
Normal file
After Width: | Height: | Size: 42 KiB |
15
app/docs/postfix-tls.md
Normal file
@ -0,0 +1,15 @@
|
||||
In case your Postfix server is on another server, it's recommended to enable TLS on Postfix submission to
|
||||
secure the connection between SimpleLogin email handler and Postfix.
|
||||
|
||||
This can be enabled by adding those lines at the end of `/etc/postfix/master.cf`
|
||||
|
||||
```
|
||||
submission inet n - y - - smtpd
|
||||
-o syslog_name=postfix/submission
|
||||
-o smtpd_tls_security_level=encrypt
|
||||
-o smtpd_sasl_auth_enable=yes
|
||||
-o smtpd_tls_auth_only=yes
|
||||
```
|
||||
|
||||
Make sure to set the `POSTFIX_SUBMISSION_TLS` variable to `true` in the SimpleLogin `simplelogin.env` file.
|
||||
|
68
app/docs/ses.md
Normal file
@ -0,0 +1,68 @@
|
||||
Contribution from https://github.com/havedill/
|
||||
|
||||
## Integrating with Amazon SES
|
||||
|
||||
If you're self hosting, here is the method I used to route emails through Amazon's SES service.
|
||||
|
||||
For me, when hosting on AWS the public IP is widely blacklisted for abuse. If you have an SES account, you are whitelisted, use TLS, and amazon creates the DKIM records.
|
||||
|
||||
First, I modify the postfix inet protocols to only route via IPv4: in `/etc/postfix/main.cf`, change `inet_protocols = ipv4`
|
||||
|
||||
### Amazon Simple Email Service Console:
|
||||
|
||||
First, verify your domain with SES, and check off "Generate DKIM Records".
|
||||
|
||||
<img src=https://i.imgur.com/9KeIlhA.png>
|
||||
|
||||
I use Route53, so pressing the Use Route53 button will automatically generate my DNS values. If you do not use Route53, you will have to create them on your DNS provider.
|
||||
|
||||
If you do choose route53, this is what generating the record sets looks like
|
||||
<img src=https://i.imgur.com/8FSHehx.png>
|
||||
|
||||
Now, in SES we need to generate SMTP Credentials to use. Go to the SMTP settings tab, and create credentails. Also note your server name, port, etc.
|
||||
|
||||
<img src=https://i.imgur.com/FcFjrCO.png>
|
||||
|
||||
Now on your server, run the following (Updating the SMTP DNS address to match what you see in the SMTP settings tab of SES)
|
||||
```
|
||||
sudo postconf -e "relayhost = [email-smtp.us-east-1.amazonaws.com]:587" \
|
||||
"smtp_sasl_auth_enable = yes" \
|
||||
"smtp_sasl_security_options = noanonymous" \
|
||||
"smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd" \
|
||||
"smtp_use_tls = yes" \
|
||||
"smtp_tls_security_level = may" \
|
||||
"smtp_tls_note_starttls_offer = yes"
|
||||
```
|
||||
|
||||
Now let's create `/etc/postfix/sasl_passwd` and inside put your SMTP Setting values;
|
||||
`[email-smtp.us-east-1.amazonaws.com]:587 SMTPUSERNAME:SMTPPASSWORD`
|
||||
|
||||
Create a hashmap with `sudo postmap hash:/etc/postfix/sasl_passwd`
|
||||
|
||||
Secure the files (optional but recommended)
|
||||
```
|
||||
sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
|
||||
sudo chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
|
||||
```
|
||||
|
||||
For Ubuntu, we point postfix to the CA Certs;
|
||||
|
||||
```bash
|
||||
sudo postconf -e 'smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt'
|
||||
```
|
||||
|
||||
Also make sure that Postfix is able to authenticate successfully by installing the SASL package:
|
||||
|
||||
```bash
|
||||
sudo apt install libsasl2-modules
|
||||
```
|
||||
|
||||
Then restart postfix
|
||||
|
||||
```bash
|
||||
sudo systemctl restart postfix
|
||||
```
|
||||
|
||||
and you should see the mail in `/var/log/mail.log` and in your alias emails routed through Amazons servers!
|
||||
|
||||
<img src=https://i.imgur.com/0qLiqmH.png>
|
60
app/docs/ssl.md
Normal file
@ -0,0 +1,60 @@
|
||||
# SSL, HTTPS, and HSTS
|
||||
|
||||
It's highly recommended to enable SSL/TLS on your server, both for the web app and email server.
|
||||
|
||||
## Using Certbot to get a certificate
|
||||
|
||||
This doc will use https://letsencrypt.org to get a free SSL certificate for app.mydomain.com that's used by both Postfix and Nginx. Let's Encrypt provides Certbot, a tool to obtain and renew SSL certificates.
|
||||
|
||||
To install Certbot, please follow instructions on https://certbot.eff.org
|
||||
|
||||
Then obtain a certificate for Nginx, use the following command. You'd need to provide an email so Let's Encrypt can send you notifications when your domain is about to expire.
|
||||
|
||||
```bash
|
||||
sudo certbot --nginx
|
||||
```
|
||||
|
||||
After this step, you should see some "managed by Certbot" lines in `/etc/nginx/sites-enabled/simplelogin`
|
||||
|
||||
### Securing Postfix
|
||||
|
||||
Now let's use the new certificate for our Postfix.
|
||||
|
||||
Replace these lines in /etc/postfix/main.cf
|
||||
|
||||
```
|
||||
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
|
||||
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```
|
||||
smtpd_tls_cert_file = /etc/letsencrypt/live/app.mydomain.com/fullchain.pem
|
||||
smtpd_tls_key_file = /etc/letsencrypt/live/app.mydomain.com/privkey.pem
|
||||
```
|
||||
|
||||
Make sure to replace app.mydomain.com with your own domain.
|
||||
|
||||
### Updating `simplelogin.env`
|
||||
|
||||
Make sure to change the `URL` in `simplelogin.env` to `https://app.mydomain.com`, otherwise not all page assets will load securely, and some functionality (e.g. Webauthn) will break.
|
||||
You will need to reload the docker containers for this to take effect.
|
||||
|
||||
## HTTP Strict Transport Security (HSTS)
|
||||
|
||||
HSTS is an extra step you can take to protect your web app from certain man-in-the-middle attacks. It does this by specifying an amount of time (usually a really long one) for which you should only accept HTTPS connections, not HTTP ones. Because of this **you should only enable HSTS once you know HTTPS is working correctly**, as otherwise you may find your browser blocking you from accessing your own web app.
|
||||
|
||||
To enable HSTS, add the following line to the `server` block of the Nginx configuration file:
|
||||
|
||||
```
|
||||
add_header Strict-Transport-Security "max-age: 31536000; includeSubDomains" always;
|
||||
```
|
||||
|
||||
(The `max-age` is the time in seconds to not permit a HTTP connection, in this case it's one year.)
|
||||
|
||||
Now, reload Nginx:
|
||||
|
||||
```bash
|
||||
sudo systemctl reload nginx
|
||||
```
|
65
app/docs/troubleshooting.md
Normal file
@ -0,0 +1,65 @@
|
||||
# Troubleshooting
|
||||
|
||||
## A. If you can't receive a welcome email when signing up
|
||||
|
||||
This can either mean:
|
||||
|
||||
1) Postfix can't send emails to your mailbox
|
||||
2) The `sl-app` container can't connect to Postfix (run on the host)
|
||||
|
||||
### A.1
|
||||
To test 1), running `swaks --to your-mailbox@mail.com` should send you an email.
|
||||
Make sure to replace `your-mailbox@mail.com` by your mailbox address.
|
||||
`swaks` can be installed with `sudo apt install swaks` on Debian-based OS.
|
||||
|
||||
### A.2
|
||||
Once 1) works, we can test the 2) by
|
||||
|
||||
a) first connecting to the container by `docker exec -it sl-app bash`
|
||||
b) then run the following commands
|
||||
|
||||
```bash
|
||||
apt update
|
||||
apt install telnet -y
|
||||
telnet 10.0.0.1 25
|
||||
```
|
||||
|
||||
If the `telnet 10.0.0.1 25` doesn't work, it means Postfix can't be reached from the docker container.
|
||||
This means an issue with the Docker network.
|
||||
|
||||
You can then try `telnet 172.17.0.1 25` as `172.17.0.1` is *usually* the host IP address. If this works, then you can set
|
||||
the `POSTFIX_SERVER=172.17.0.1` in your SimpleLogin config file `~/simplelogin.env` and re-run all the containers.
|
||||
|
||||
If not, please run through the self-hosting instructions and make sure no step is missed.
|
||||
|
||||
## B. You send an email to your alias and can't receive the forwarded email on your mailbox
|
||||
|
||||
This can be either due to:
|
||||
|
||||
1) Postfix doesn't recognize the alias domain
|
||||
2) Postfix can't connect to the `sl-email` container
|
||||
3) `sl-email` container can't connect to Postfix
|
||||
4) Postfix can't send emails to
|
||||
|
||||
### B.1
|
||||
For 1), this can mean the `/etc/postfix/pgsql-relay-domains.cf` and `/etc/postfix/pgsql-transport-maps.cf` aren't correctly set up.
|
||||
To test 1), `postmap -q mydomain.com pgsql:/etc/postfix/pgsql-relay-domains.cf` should return `mydomain.com`.
|
||||
|
||||
And `postmap -q not-exist.com pgsql:/etc/postfix/pgsql-relay-domains.cf` should return nothing.
|
||||
|
||||
`postmap -q mydomain.com pgsql:/etc/postfix/pgsql-transport-maps.cf` should return `smtp:127.0.0.1:20381`
|
||||
|
||||
And `postmap -q not-exist.com pgsql:/etc/postfix/pgsql-transport-maps.cf` should return nothing.
|
||||
|
||||
### B.2
|
||||
For 2), you can check in the `sl-email` log by running `docker logs sl-email` and if the incoming email doesn't appear there,
|
||||
then it means Postfix can't connect to the `sl-email` container. Please run through the self-hosting instructions and
|
||||
make sure no step is missed.
|
||||
|
||||
### B.3
|
||||
|
||||
For 3), you can check in the `sl-email` log by running `docker logs sl-email` and make sure there's no error there.
|
||||
|
||||
### B.4
|
||||
For 4), please refer to the A.1 section to make sure Postfix can send emails to your mailbox.
|
||||
|
16
app/docs/ufw.md
Normal file
@ -0,0 +1,16 @@
|
||||
SimpleLogin needs to have the following ports open:
|
||||
- 22: so you SSH into the server
|
||||
- 25: to receive the incoming emails
|
||||
- 80 and optionally 443 for SimpleLogin webapp
|
||||
|
||||
If you use `UFW` Firewall, you could run the following commands to open these ports:
|
||||
|
||||
```bash
|
||||
sudo ufw allow 22
|
||||
sudo ufw allow 25
|
||||
sudo ufw allow 80
|
||||
|
||||
# optional, enable 443 if you set up TLS for the webapp
|
||||
sudo ufw allow 443
|
||||
```
|
||||
|
210
app/docs/upgrade.md
Normal file
@ -0,0 +1,210 @@
|
||||
Upgrading SimpleLogin usually consists of simply pulling the latest version, stop & re-run SimpleLogin containers: *sl-migration*, *sl-app* and *sl-email*. It's not necessary to restart *sl-db* as it uses Postgres image.
|
||||
|
||||
No emails or any data is lost in the upgrade process. The same process is by the way used by the SimpleLogin SaaS version which is deployed several times per day.
|
||||
|
||||
Sometimes upgrading to a major version might require running a manual migration. This is for example the case when upgrading to 2.0.0. In this case please follow the corresponding migration first before running these scripts.
|
||||
|
||||
If you are running versions prior to 3x, please:
|
||||
|
||||
1. first upgrade to 2.1.2 then
|
||||
2. upgrade to the latest version which is 3.4.0
|
||||
|
||||
<details>
|
||||
<summary>After upgrade to 3x from 2x</summary>
|
||||
<p>
|
||||
|
||||
3x has some data structure changes that cannot be automatically upgraded from 2x.
|
||||
Once you have upgraded your installation to 3x, please run the following scripts to make your data fully compatible with 3x
|
||||
|
||||
First connect to your SimpleLogin container shell:
|
||||
|
||||
```bash
|
||||
docker exec -it sl-app python shell.py
|
||||
```
|
||||
|
||||
Then copy and run this below script:
|
||||
|
||||
```python
|
||||
from app.extensions import db
|
||||
from app.models import AliasUsedOn, Contact, EmailLog
|
||||
|
||||
for auo in AliasUsedOn.query.all():
|
||||
auo.user_id = auo.alias.user_id
|
||||
db.session.commit()
|
||||
|
||||
for contact in Contact.query.all():
|
||||
contact.user_id = contact.alias.user_id
|
||||
db.session.commit()
|
||||
|
||||
for email_log in EmailLog.query.all():
|
||||
email_log.user_id = email_log.contact.user_id
|
||||
|
||||
db.session.commit()
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Upgrade to 2.1.0 from 2.0.0</summary>
|
||||
<p>
|
||||
|
||||
2.1.0 comes with PGP support. If you use PGP, please follow these steps to enable this feature:
|
||||
|
||||
1) In your home directory (where `dkim.key` is located), create directory to store SimpleLogin data
|
||||
|
||||
```bash
|
||||
mkdir sl
|
||||
mkdir sl/pgp # to store PGP key
|
||||
mkdir sl/db # to store database
|
||||
```
|
||||
|
||||
2) Then add this line to your config simplelogin.env file
|
||||
|
||||
```
|
||||
GNUPGHOME=/sl/pgp # where to store PGP keys
|
||||
```
|
||||
|
||||
Now you can follow the usual steps to upgrade SimpleLogin.
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Upgrade to 2.0.0</summary>
|
||||
<p>
|
||||
|
||||
2.0.0 comes with mailbox feature that requires running a script that puts all existing users to "full-mailbox" mode.
|
||||
|
||||
1) First please make sure to upgrade to 1.0.5 which is the latest version before 2.0.0.
|
||||
|
||||
2) Then connect to your SimpleLogin container shell:
|
||||
|
||||
```bash
|
||||
docker exec -it sl-app python shell.py
|
||||
```
|
||||
|
||||
3) Finally copy and run this below script:
|
||||
|
||||
```python
|
||||
"""This ad-hoc script is to be run when upgrading from 1.0.5 to 2.0.0
|
||||
"""
|
||||
from app.extensions import db
|
||||
from app.log import LOG
|
||||
from app.models import Mailbox, Alias, User
|
||||
|
||||
for user in User.query.all():
|
||||
if user.default_mailbox_id:
|
||||
# already run the migration on this user
|
||||
continue
|
||||
|
||||
# create a default mailbox
|
||||
default_mb = Mailbox.get_by(user_id=user.id, email=user.email)
|
||||
if not default_mb:
|
||||
LOG.d("create default mailbox for user %s", user)
|
||||
default_mb = Mailbox.create(user_id=user.id, email=user.email, verified=True)
|
||||
db.session.commit()
|
||||
|
||||
# assign existing alias to this mailbox
|
||||
for gen_email in Alias.query.filter_by(user_id=user.id):
|
||||
if not gen_email.mailbox_id:
|
||||
LOG.d("Set alias %s mailbox to default mailbox", gen_email)
|
||||
gen_email.mailbox_id = default_mb.id
|
||||
|
||||
# finally set user to full_mailbox
|
||||
user.full_mailbox = True
|
||||
user.default_mailbox_id = default_mb.id
|
||||
db.session.commit()
|
||||
```
|
||||
</p>
|
||||
</details>
|
||||
|
||||
## Upgrade to the latest version 3.4.0
|
||||
|
||||
```bash
|
||||
# Pull the latest version
|
||||
sudo docker pull simplelogin/app:3.4.0
|
||||
|
||||
# Stop SimpleLogin containers
|
||||
sudo docker stop sl-email sl-migration sl-app sl-db sl-job-runner
|
||||
|
||||
# Make sure to remove these containers to avoid conflict
|
||||
sudo docker rm -f sl-email sl-migration sl-app sl-db
|
||||
|
||||
# create ./sl/upload/ if not exist
|
||||
mkdir -p ./sl/upload/
|
||||
|
||||
# Run the database container. Make sure to replace `myuser` and `mypassword`
|
||||
docker run -d \
|
||||
--name sl-db \
|
||||
-e POSTGRES_PASSWORD=mypassword \
|
||||
-e POSTGRES_USER=myuser \
|
||||
-e POSTGRES_DB=simplelogin \
|
||||
-p 127.0.0.1:5432:5432 \
|
||||
-v $(pwd)/sl/db:/var/lib/postgresql/data \
|
||||
--restart always \
|
||||
--network="sl-network" \
|
||||
postgres:12.1
|
||||
|
||||
# Run the database migration
|
||||
sudo docker run --rm \
|
||||
--name sl-migration \
|
||||
-v $(pwd)/sl:/sl \
|
||||
-v $(pwd)/sl/upload:/code/static/upload \
|
||||
-v $(pwd)/dkim.key:/dkim.key \
|
||||
-v $(pwd)/dkim.pub.key:/dkim.pub.key \
|
||||
-v $(pwd)/simplelogin.env:/code/.env \
|
||||
--network="sl-network" \
|
||||
simplelogin/app:3.4.0 flask db upgrade
|
||||
|
||||
# Run init data
|
||||
sudo docker run --rm \
|
||||
--name sl-init \
|
||||
-v $(pwd)/sl:/sl \
|
||||
-v $(pwd)/sl/upload:/code/static/upload \
|
||||
-v $(pwd)/simplelogin.env:/code/.env \
|
||||
-v $(pwd)/dkim.key:/dkim.key \
|
||||
-v $(pwd)/dkim.pub.key:/dkim.pub.key \
|
||||
--network="sl-network" \
|
||||
simplelogin/app:3.4.0 python init_app.py
|
||||
|
||||
# Run the webapp container
|
||||
sudo docker run -d \
|
||||
--name sl-app \
|
||||
-v $(pwd)/sl:/sl \
|
||||
-v $(pwd)/sl/upload:/code/static/upload \
|
||||
-v $(pwd)/simplelogin.env:/code/.env \
|
||||
-v $(pwd)/dkim.key:/dkim.key \
|
||||
-v $(pwd)/dkim.pub.key:/dkim.pub.key \
|
||||
-p 127.0.0.1:7777:7777 \
|
||||
--restart always \
|
||||
--network="sl-network" \
|
||||
simplelogin/app:3.4.0
|
||||
|
||||
# Run the email handler container
|
||||
sudo docker run -d \
|
||||
--name sl-email \
|
||||
-v $(pwd)/sl:/sl \
|
||||
-v $(pwd)/sl/upload:/code/static/upload \
|
||||
-v $(pwd)/simplelogin.env:/code/.env \
|
||||
-v $(pwd)/dkim.key:/dkim.key \
|
||||
-v $(pwd)/dkim.pub.key:/dkim.pub.key \
|
||||
-p 127.0.0.1:20381:20381 \
|
||||
--restart always \
|
||||
--network="sl-network" \
|
||||
simplelogin/app:3.4.0 python email_handler.py
|
||||
|
||||
# Run the job runner
|
||||
docker run -d \
|
||||
--name sl-job-runner \
|
||||
-v $(pwd)/sl:/sl \
|
||||
-v $(pwd)/sl/upload:/code/static/upload \
|
||||
-v $(pwd)/simplelogin.env:/code/.env \
|
||||
-v $(pwd)/dkim.key:/dkim.key \
|
||||
-v $(pwd)/dkim.pub.key:/dkim.pub.key \
|
||||
--restart always \
|
||||
--network="sl-network" \
|
||||
simplelogin/app:3.4.0 python job_runner.py
|
||||
|
||||
```
|
||||
|