mydoc_install_server_ee.md 13.8 KB
Newer Older
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
1 2 3 4 5
---
title: Install Psono Server EE
tags: [installation, server]
summary: "Install instruction for the Enterprise Edition of the Psono server"
sidebar: mydoc_sidebar
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
6
permalink: mydoc_install_server_ee.html
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20
folder: mydoc
---

## Preamble

At this point we assume that you already have a postgres database running, ready for connections. If not follow this
[guide to setup postgres](mydoc_install_postgres.html).

## Installation with Docker

1.  Create a settings.yaml in e.g. /opt/docker/psono/ with the following content
    
	```yaml
	# generate the following six parameters with the following command
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
21
	# docker run --rm -ti psono/psono-server:latest python3 ./psono/manage.py generateserverkeys
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
	SECRET_KEY: 'SOME SUPER SECRET KEY THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
	ACTIVATION_LINK_SECRET: 'SOME SUPER SECRET ACTIVATION LINK SECRET THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
	DB_SECRET: 'SOME SUPER SECRET DB SECRET THAT SHOULD BE RANDOM AND 32 OR MORE DIGITS LONG'
	EMAIL_SECRET_SALT: '$2b$12$XUG.sKxC2jmkUvWQjg53.e'
	PRIVATE_KEY: '302650c3c82f7111c2e8ceb660d32173cdc8c3d7717f1d4f982aad5234648fcb'
	PUBLIC_KEY: '02da2ad857321d701d754a7e60d0a147cdbc400ff4465e1f57bc2d9fbfeddf0b'

	# The URL of the web client (path to e.g activate.html without the trailing slash)
	# WEB_CLIENT_URL: 'https://www.psono.pw'

	# Switch DEBUG to false if you go into production
	DEBUG: False

	# Adjust this according to Django Documentation https://docs.djangoproject.com/en/1.10/ref/settings/
	ALLOWED_HOSTS: ['*']

	# Should be your domain without "www.". Will be the last part of the username
	ALLOWED_DOMAINS: ['psono.pw']

	# If you want to disable registration, you can comment in the following line
	# ALLOW_REGISTRATION: False

Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
44 45 46
	# If you want to disable the lost password functionality, you can comment in the following line
	# ALLOW_LOST_PASSWORD: False

Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
47 48 49 50
	# If you want to restrict registration to some email addresses you can specify here a list of domains to filter
	# REGISTRATION_EMAIL_FILTER: ['company1.com', 'company2.com']

	# Should be the URL of the host under which the host is reachable
51
	# If you open the url and append /info/ to it you should have a text similar to {"info":"{\"version\": \"....}
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
52 53 54
	HOST_URL: 'https://www.psono.pw/server'

	# The email used to send emails, e.g. for activation
55 56
	# ATTENTION: If executed in a docker container, then "localhost" will resolve to the docker container, so
	# "localhost" will not work as host. Use the public IP or DNS record of the server.
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
57 58 59 60 61 62 63 64 65 66 67 68 69
	EMAIL_FROM: 'the-mail-for-for-example-useraccount-activations@test.com'
	EMAIL_HOST: 'localhost'
	EMAIL_HOST_USER: ''
	EMAIL_HOST_PASSWORD : ''
	EMAIL_PORT: 25
	EMAIL_SUBJECT_PREFIX: ''
	EMAIL_USE_TLS: False
	EMAIL_USE_SSL: False
	EMAIL_SSL_CERTFILE:
	EMAIL_SSL_KEYFILE:
	EMAIL_TIMEOUT:

	# In case one wants to use mailgun, comment in below lines and provide the mailgun access key and server name
70
	# EMAIL_BACKEND: 'anymail.backends.mailgun.EmailBackend'
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
	# MAILGUN_ACCESS_KEY: ''
	# MAILGUN_SERVER_NAME: ''

	# In case you want to offer Yubikey support, create a pair of credentials here https://upgrade.yubico.com/getapikey/
	# and update the following two lines before commenting them in
	# YUBIKEY_CLIENT_ID: '123456'
	# YUBIKEY_SECRET_KEY: '8I65IA6ASDFIUHGIH5021FKJA='

	# If you have own Yubico servers, you can specify here the urls as a list
	# YUBICO_API_URLS: ['https://api.yubico.com/wsapi/2.0/verify']

	# Cache enabled without belows Redis may lead to unexpected behaviour

	# Cache with Redis
	# By default you should use something different than database 0 or 1, e.g. 13 (default max is 16, can be configured in
	# redis.conf) possible URLS are:
	#    redis://[:password]@localhost:6379/0
	#    rediss://[:password]@localhost:6379/0
	#    unix://[:password]@/path/to/socket.sock?db=0
	# CACHE_ENABLE: False
	# CACHE_REDIS: False
	# CACHE_REDIS_LOCATION: 'redis://127.0.0.1:6379/13'

	# Disables Throttling (necessary for unittests to pass) by overriding the cache with a dummy cache
	# https://docs.djangoproject.com/en/1.11/topics/cache/#dummy-caching-for-development
	# THROTTLING: False

98 99 100 101 102 103 104 105 106 107 108 109 110 111
	# The server will automatically connect to the license server to get a license for 10 users.
	# For paying customers we offer the opportunity to get an offline license code.
	#
	# LICENSE_CODE: |
	#   0abcdefg...
	#   1abcdefg...
	#   2abcdefg...
	#   3abcdefg...
	#   4abcdefg...
	#   5abcdefg...
	#   6abcdefg...
	#   7abcdefg...
	#   8abcdefg...

Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
112 113 114
	# Enables the management API, required for the psono-admin-client / admin portal
	# MANAGEMENT_ENABLED: False

115 116 117 118 119 120
	# Enables the fileserver API, required for the psono-fileserver
	# FILESERVER_HANDLER_ENABLED: False

	# Enables files for the client
	# FILES_ENABLED: False

Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
121
	# Allows that users can search for partial usernames
122 123 124 125
	# ALLOW_USER_SEARCH_BY_USERNAME_PARTIAL: True

	# Allows that users can search for email addresses too
	# ALLOW_USER_SEARCH_BY_EMAIL: True
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
126 127 128 129

	# Allows admins to limit the offered second factors in the client
	# ALLOWED_SECOND_FACTORS: ['yubikey_otp', 'google_authenticator', 'duo']

130 131 132
	# Enforce the user to setup a second factor
	# COMPLIANCE_ENFORCE_2FA: True

133 134 135
	# Disables recovery codes
	# COMPLIANCE_DISABLE_RECOVERY_CODES: True

136 137 138
	# Disables file repositories
	# COMPLIANCE_DISABLE_FILE_REPOSITORIES: True

139 140 141 142 143 144
	# Disables emergency codes
	# COMPLIANCE_DISABLE_EMERGENCY_CODES: True

	# Disables the export of passwords
	# COMPLIANCE_DISABLE_EXPORT: True

145 146 147
	# Disables API keys
	# COMPLIANCE_DISABLE_API_KEYS: True

Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
148 149 150 151 152 153 154
	# Only necessary if the psono-client runs on a sub path (no trailing slash) e.g. "https://wwww.psono.pw"
	# WEB_CLIENT_URL: ''

	# Prevents the use of the last X passwords. 0 disables it.
	# DISABLE_LAST_PASSWORDS: 0

	# If you want to use LDAP, then you can configure it like this
155 156 157
	#
	# 		LDAP_URL: Any valid LDAP string, preferable with ldaps. usual urls are 'ldaps://example.com:636' or 'ldap://192.168.0.1:389'
	#		LDAP_DOMAIN: Your LDAP domain, is added at the end of the username to form the full username
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
158 159
	#		LDAP_BIND_DN: One User that can be used to search your LDAP
	#		LDAP_BIND_PASS: The password of the user specified in LDAP_BIND_DN
160
	#		LDAP_ATTR_GUID: The uuid attribute. e.g. on Windows 'objectGUID', but common are 'GUID' or 'entryUUID', default 'objectGUID'
161 162 163 164 165 166
	#		LDAP_OBJECT_CLASS_USER: The objectClass value to filter user objects e.g. on Windows 'user', default 'user'
	#		LDAP_OBJECT_CLASS_GROUP: The objectClass value to filter group objects e.g. on Windows 'group', default 'group'
	#		LDAP_SEARCH_USER_DN: The "root" from which downwards we search for the users
	#		LDAP_SEARCH_GROUP_DN: The "root" from which downwards we search for the groups
	#		LDAP_ATTR_USERNAME: The username attribute to try to match against. e.g. on Windows 'sAMAccountName', default 'sAMAccountName'
	#		LDAP_ATTR_EMAIL: The attribute of the user objects that holds the mail address e.g. on Windows 'mail', default 'mail'
167
	#		LDAP_ATTR_GROUPS: The attribute of the user objects that holds the groups e.g. on Windows 'memberOf', default 'memberOf'
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
168
	#		LDAP_CA_CERT_FILE: If you want to use ldaps and don't have a publicly trusted and signed certificate you can specify here the path to your ca certificate
169
	#
170 171 172 173
	# To help you setup LDAP, we have created a small "testldap" command that should make things alot easier. You can execute it like:
	# python3 psono/manage.py testldap username@something.com thePassWord
	#
	# For Windows AD it could look like this:
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
174 175 176 177 178 179
	#
	# LDAP : [
	#     {
	#         'LDAP_URL': 'ldaps://192.168.0.1:636',
	#         'LDAP_DOMAIN': 'example.com',
	#         'LDAP_BIND_DN': 'CN=LDAPPsono,OU=UsersTech,OU=example.com,DC=example,DC=com',
180
	#         'LDAP_BIND_PASS': 'hopefully_not_123456',
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
181
	#         'LDAP_SEARCH_USER_DN': 'OU=Users,OU=example.com,DC=example,DC=com',
182
	#         'LDAP_SEARCH_GROUP_DN': 'OU=Groups,OU=example.com,DC=example,DC=com',
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
183 184
	#     },
	# ]
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
	#
	# For OpenLDAP it could look like this:
	#
	# LDAP : [
	#     {
	#         'LDAP_URL': 'ldaps://192.168.0.1:636',
	#         'LDAP_DOMAIN': 'example.com',
	#         'LDAP_BIND_DN': 'CN=LDAPPsono,OU=UsersTech,OU=example.com,DC=example,DC=com',
	#         'LDAP_BIND_PASS': 'hopefully_not_123456',
	#         'LDAP_SEARCH_USER_DN': 'OU=Users,OU=example.com,DC=example,DC=com',
	#         'LDAP_SEARCH_GROUP_DN': 'OU=Groups,OU=example.com,DC=example,DC=com',
	#         'LDAP_OBJECT_CLASS_USER': 'simpleSecurityObject',
	#         'LDAP_ATTR_USERNAME': 'cn',
	#         'LDAP_ATTR_GUID': 'entryUUID',
	#     },
	# ]
201 202 203
	#
	# ATTENTION: API kays currently bypass LDAP authentication, that means API keys can still access secrets even if the
	# user was disabled in LDAP. API keys can be disabled with COMPLIANCE_DISABLE_API_KEYS
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
204 205 206 207 208 209 210 211

	# You also have to comment in the line below if you want to use LDAP (default: ['AUTHKEY'])
	# AUTHENTICATION_METHODS: ['AUTHKEY', 'LDAP']

	# Enable Audit logging
    # LOGGING_AUDIT: True

    # To log to another destination you can specify this here, default '/var/log/psono'
212 213 214
    # Never really necessary, as we will run the psono server in a docker container and can mount /var/log/psono to any
    # location on the underlying docker host.
    # LOGGING_AUDIT_FOLDER: '/var/log/psono'
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
215 216 217 218 219 220 221 222 223

    # If you prefer server time over utc, you can do that like below (default 'time_utc')
    # LOGGING_AUDIT_TIME: 'time_server'

	# If the server logs too much for you can either whitelist or blacklist events by their event code. (default: [])
	# LOGGING_AUDIT_WHITELIST: []
	# LOGGING_AUDIT_BLACKLIST: []

	# Your Postgres Database credentials
224 225
	# ATTENTION: If executed in a docker container, then "localhost" will resolve to the docker container, so
	# "localhost" will not work as host. Use the public IP or DNS record of the server.
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
	DATABASES:
	    default:
	        'ENGINE': 'django.db.backends.postgresql_psycopg2'
	        'NAME': 'psono'
	        'USER': 'psono'
	        'PASSWORD': 'password'
	        'HOST': 'localhost'
	        'PORT': '5432'
	# for master / slave replication setup comment in the following (all reads will be redirected to the slave
	#    slave:
	#        'ENGINE': 'django.db.backends.postgresql_psycopg2'
	#        'NAME': 'YourPostgresDatabase'
	#        'USER': 'YourPostgresUser'
	#        'PASSWORD': 'YourPostgresPassword'
	#        'HOST': 'YourPostgresHost'
	#        'PORT': 'YourPostgresPort'

	# The path to the template folder can be "shadowed" if required later
	TEMPLATES: [
	    {
	        'BACKEND': 'django.template.backends.django.DjangoTemplates',
	        'DIRS': ['/root/psono/templates'],
	        'APP_DIRS': True,
	        'OPTIONS': {
	            'context_processors': [
	                'django.template.context_processors.debug',
	                'django.template.context_processors.request',
	                'django.contrib.auth.context_processors.auth',
	                'django.contrib.messages.context_processors.messages',
	            ],
	        },
	    },
	]
	```

    {% include note.html content="Update database credentials / secrets / paths like described in the comments" %}

263 264 265 266 267
2.  Create the local logging directory for the audit logs

		sudo mkdir -p /var/log/psono

3.  Test E-Mail
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
268 269 270 271 272 273 274 275 276 277 278 279 280

    The most tedious step is usually for me to get e-mail working.
    To make this step easier, we offer a small test script which will
    send a test e-mail.
    
    To send a test e-mail to `something@something.com` execute:

        docker run --rm \
          -v /path/to/modified/settings.yaml:/root/.psono_server/settings.yaml \
          -ti psono/psono-server-enterprise:latest python3 ./psono/manage.py sendtestmail something@something.com

    If you receive this test e-mail, e-mail should be configured proper.
    
281
4.  Prepare the database
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
282 283 284 285 286

        docker run --rm \
          -v /path/to/modified/settings.yaml:/root/.psono_server/settings.yaml \
          -ti psono/psono-server-enterprise:latest python3 ./psono/manage.py migrate
    
287
5.  Run the dockered psono server image and expose the server port
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
288 289 290 291

        docker run --name psono-server-enterprise \
            --sysctl net.core.somaxconn=65535 \
            -v /path/to/modified/settings.yaml:/root/.psono_server/settings.yaml \
292
            -v /path/to/log/folder:/var/log/psono \
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
293 294 295
            -d --restart=unless-stopped -p 10100:80 psono/psono-server-enterprise:latest
            
    This will start the Psono server on port 10100. 
296
    If you open now http://your-ip:10100/info/ you should see something like this:
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
297

298
        {"info":"{\"version\": \"....}
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
299 300 301

    If not, please make sure you have no firewall on the server blocking you.
	
302
6.  Setup cleanup job
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
303 304 305 306 307 308 309 310 311

    Execute the following command:

	    crontab -e
	    
	and add the following line:
	
        30 2 * * * docker run --rm -v /path/to/modified/settings.yaml:/root/.psono_server/settings.yaml -ti psono/psono-server-enterprise:latest python3 ./psono/manage.py cleartoken >> /var/log/cron.log 2>&1
	
312
7.  Setup Reverse Proxy
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
313 314 315 316 317 318 319 320 321 322 323 324 325

	To run the Psono password manager in production, a reverse proxy is needed, to handle the ssl offloading and glue the psono server
	and webclient together. Follow the [guide to setup reverse proxy](mydoc_install_reverse_proxy.html) as a next step.


## Note: Installation behind Firewall

If you have put your installation behind a firewall, you have to whitelist some ports / adjust some settings, that all
features work:

* Outgoing TCP / UDP 123 connection to time.google.com: Psono requires a synced time for various reasons (Google Authenticator, YubiKey, Throttling, Replay protection, ...)
Therefore it has a healthcheck, to compare the local time to a time server (by default time.google.com). You can specify your own timeserver in the settings.yaml with the "TIME_SERVER" parameter.
* Outgoing TCP 443 connection to api*.yubico.com: Psono validates YubiKey OTP tokens against the official Yubikey Servers. You can use an own YubiKey server with the "YUBICO_API_URLS" parameter in the settings.yaml
326
* Outgoing TCP 443 connection to api*.duosecurity.com: Psono initiates connection a to the Duo api server, whenever someone uses Duo's 2 Factor authentication.
Sascha Pfeiffer's avatar
Sascha Pfeiffer committed
327 328

{% include links.html %}