Commit Graph

376 Commits

Author SHA1 Message Date
Joshua Tauberer 16e2350fef revise the description of A records on domains: the A record must be present for good deliverability so that the envelope domain resolves, but it doesn't have to resolve to this machine 2014-09-15 06:00:50 -04:00
Christian 9631fab7b2 Changed incomming-email-input to type text
The input type="email" validation won't allow "@example.com", which is needed for catch-all-aliases.
2014-09-12 18:08:33 +02:00
Joshua Tauberer 196e42e8b5 don't automatically create an alias if a user account already exists by that name
In the event the first user is an address that we'd normally create as an alias,
we'd generate a loop from the alias to the administrative alias to the first user
account (which was the alias again).

hopefully fixes #186
2014-09-09 11:41:47 +00:00
Joshua Tauberer f09da719f7 show the response from spamhaus.org in the status checks output 2014-09-08 20:27:26 +00:00
Joshua Tauberer e9e95cbed5 tweak backup explanatory text 2014-09-08 20:12:31 +00:00
Joshua Tauberer 98fc449b49 only hold onto backups for 14 days (not 31) and show when the backups will be deleted in the control panel 2014-09-08 20:09:18 +00:00
Joshua Tauberer bab8b515ea new logic for determining when to take a full backup 2014-09-08 19:42:54 +00:00
Joshua Tauberer cce6bc02a8 add links to IANA tables for DNSSEC algorithm/digest number assignemnts 2014-09-07 10:59:20 -04:00
Joshua Tauberer 110e0f90d9 dns: move the quoting of TXT records to when we write the zone file so that we can display it unquoted in the External DNS instructions 2014-09-07 11:42:20 +00:00
Joshua Tauberer b5122770cc tweak admin template for external DNS 2014-09-07 07:22:39 -04:00
Joshua Tauberer 03f9358de4 when checking SSL certs are OK, check for wildcard certificates
fixes #175 (hopefully)
2014-09-03 17:31:47 +00:00
Joshua Tauberer f77f1e656c split CardDAV instrctions into a new page and add CalDAV instructions; create nice redirects at /cloud/calendar and /cloud/contacts 2014-09-03 10:51:19 +00:00
Joshua Tauberer b420e560c3 dont show 'make admin' on archived mailbox accounts and other control panel cleanup 2014-09-03 10:17:46 +00:00
Joshua Tauberer 7a449c76a1 set the DNS TTL to 30 minutes rather than 1 day
Also updating the values for secondary DNS, but we're not set up
for secondary DNS so it won't matter.

see #172
2014-09-01 23:06:55 +00:00
Joshua Tauberer 3853e8dd93 show the status of backups in the control panel 2014-09-01 13:06:53 +00:00
Joshua Tauberer 10a37cd033 add SSHFP records to DNS 2014-08-27 12:59:40 +00:00
Joshua Tauberer 684d9b3c70 prettify the custom DNS docs 2014-08-27 12:57:47 +00:00
Joshua Tauberer 699923d605 Merge pull request #166 from benschumacher/master
Fix typo in dns_update.py.
2014-08-26 16:13:11 -04:00
Ben Schumacher d5efb05f31 Fix typo in dns_update.py. 2014-08-26 15:58:34 -04:00
Sebastian Kosch 2afd0be591 Replace spaces by tabs in 106-109 2014-08-26 12:16:20 -04:00
Joshua Tauberer 92c7815d2c Merge pull request #156 from skosch/patch-1
Allow users to insert custom nginx configuration directives through new optional files.
2014-08-26 10:24:22 -04:00
Joshua Tauberer 06a4046d13 fix link to /cloud in the admin, fixes #160 2014-08-26 11:51:47 +00:00
Joshua Tauberer 9b8d85de45 if there are no admins when trying to access the control panel, tell the user how to make an admin from SSH 2014-08-26 11:31:45 +00:00
Joshua Tauberer b76cbae5a0 document the DNS API in the control panel
see #140, #155, df20d447a9
2014-08-25 23:52:41 +00:00
Joshua Tauberer ed8ce16fb5 show custom DNS records in the control panel too, fixes #155 2014-08-25 23:35:44 +00:00
Joshua Tauberer a32806da32 create STORAGE_ROOT/backup/duplicity if it doesn't exist
fixes #158
2014-08-25 23:29:00 +00:00
Joshua Tauberer 18f0406541 update comments in backup.py 2014-08-25 23:28:43 +00:00
Joshua Tauberer bc9d670981 prettify mail guide 2014-08-25 23:24:41 +00:00
Sebastian Kosch 00b5c6ee9c test_domain -> domain 2014-08-25 16:02:13 -04:00
Sebastian Kosch 76ff9735cc Move custom server blocks to STORAGE_ROOT 2014-08-25 13:25:44 -04:00
Sebastian Kosch 9bfff1f679 Add server block customizations
This allows users to add a file /etc/nginx/conf.d/includes/mydomain.com.conf, the contents of which will be included in the server block for mydomain.com.
2014-08-24 17:34:15 -04:00
Joshua Tauberer df20d447a9 add an api for setting custom DNS records
Works like this:

```curl -d "" --user email:password https://.../admin/dns/set/qname/rtype/value```

where the rtype and value default to "A" and the remote IP address of the request, so that a simple, empty POST to

```https://.../admin/dns/set/desktop.mydomain.com```

will point desktop.mydomain.com to the caller's IPv4 address.

closes #140
2014-08-23 23:03:45 +00:00
Joshua Tauberer 6e3b04ce83 when generating SSL CSRs, using SHA256 as SHA1 is being phased out, per @konklone 2014-08-23 17:49:33 -04:00
Joshua Tauberer 2d5097345a move the package update check into the system status checks 2014-08-21 11:24:40 +00:00
Joshua Tauberer 294d19e0af rename whats_next.py to status_checks.py 2014-08-21 10:43:55 +00:00
Joshua Tauberer 46f3d05034 add the network checks to whats_next
* zen.spamhaus.org
* dbl.spamhaus.org
* checks if a connection to Google's MTA on port 25 works
2014-08-19 11:16:49 +00:00
Joshua Tauberer 91821adfd7 nameserver checks should be case insensitive 2014-08-18 22:41:27 +00:00
Joshua Tauberer b30d7ad80a web-based administrative UI
closes #19
2014-08-17 22:46:06 +00:00
Joshua Tauberer ba8e015795 dns_update: dont restart the opendkim process if nothing changed 2014-08-17 20:42:17 +00:00
Joshua Tauberer 919a5a8f0b whats_next: when there are multiple responses like for NS records sort the responses so we can compare to a fixed order 2014-08-17 19:55:03 +00:00
Joshua Tauberer f299825a95 in the nginx override YAML file, change how proxies are specified into a mapping 2014-08-17 19:40:45 +00:00
Joshua Tauberer 04454b35c6 (merge) CardDAV, CalDAV via ownCloud and move to z-push fork fork
Merges branch 'owncloud' of github.com:jkaberg/mailinabox
which is pull request #135, closes #135

thanks @jkaberg, @fmbiete, @owncloud
2014-08-17 15:31:08 -04:00
Joshua Tauberer f41ec93cbe management: dont raise an exception on a poorly formatted authentication header 2014-08-17 11:50:05 -04:00
Joshua Tauberer 6e380ade17 owncloud will only let users access it from the PRIMARY_HOSTNAME (due to its trusted_domains option being set statically), so only include /cloud in the nginx configuration for PRIMARY_HOSTNAME 2014-08-16 12:33:10 +00:00
Joshua Tauberer 8c9f278166 owncloud: support MOD_X_ACCEL_REDIRECT_ENABLED
This lets downloads from the file app work.
2014-08-15 23:16:54 +00:00
Joshua Tauberer e625a424fd whats_next: check that the TLSA record is correct, fixes #139 2014-08-13 19:42:49 +00:00
Joshua Tauberer 0eceb2012f use php5-fpm rather than our own custom launcher script for PHP+FastCGI 2014-08-12 11:00:54 +00:00
Joshua Tauberer 1312b0254b backup: dont remove old increments because then we lose the backup history right before the last full backup, instead let them disappear along with full backups when a whole chain becomes very old 2014-08-11 11:45:40 +00:00
Joshua Tauberer f66914d634 backup: automatically take a full backup when the sum of the increments get very large 2014-08-11 11:38:32 +00:00
Joshua Tauberer 58e300e113 backup must be full on the first run because incremental backup will fail, fixes #134 2014-08-11 07:16:58 -04:00
Joshua Tauberer e294f7c181 create the Drafts folder for users so K-9 mail doesn't poll unnecessarily, see #129 2014-08-09 16:49:57 +00:00
Joshua Tauberer b56f82cb92 make a privileges column in the users table and mark the first user as an admin 2014-08-08 12:31:22 +00:00
Joshua Tauberer 6a512042dc after creating the local encrypted backup, execute the after-backup script if the user has provided one to copy the files to a remote location 2014-08-02 14:16:08 +00:00
Joshua Tauberer 6d4fab1e6a whats_next: offer DNSSEC DS parameters rather than the full record and in validation allow for other digests than the one we suggest using
fixes #120 (hopefully), in which Gandi generates a SHA1 digest but we were only checking against a SHA256 digest

Also see http://discourse.mailinabox.email/t/how-to-set-ds-record-for-gandi-net/24/1 in which a user asks about the DS parameters that Gandi asks for.
2014-08-01 12:15:05 +00:00
Joshua Tauberer 30178ef019 add a --force flag to dns_update 2014-08-01 12:05:34 +00:00
Joshua Tauberer 168c06939d have nsd bind to the network interaface that is connected to the Internet, rather than all non-loopback network interfaces
hopefully fixes #121; thanks for the help @sfPlayer1
2014-07-29 20:07:26 -04:00
Joshua Tauberer 8042ab66ac dont serve web for domains with custom DNS records that point A/AAAA elsewhere, and in whats_next only check that an A record exists on a domain if we are serving web on the domain 2014-07-20 15:23:17 +00:00
Joshua Tauberer 8354d9732a in the custom DNS yaml config, treat 'local' as an alias for the box's own IP/IPv6 addresses 2014-07-20 14:53:55 +00:00
Joshua Tauberer 1ad9c70887 refactor custom DNS records 2014-07-20 14:48:20 +00:00
Joshua Tauberer 2e0680de4f the check for whether a custom DNS setting is valid was in the wrong place 2014-07-20 14:41:02 +00:00
sfPlayer1 89acbe4127 Update dns_update.py
Add new extra bool parameter.
2014-07-18 13:05:32 +02:00
sfPlayer1 0e893626c8 Add IPv6 glue records as well
The dns_update script didn't generate IPv6 (AAAA) glue records for the name servers.

This caused http://dnscheck.pingdom.com to complain about a mismatch between the glue records reported by the parent name server and mailinabox nsd.

Here's the failing dnscheck output for reference:
> Checking glue for ns1.my.domain.tld (1.2.3.4).
> Child glue for bgwe.eu found: ns1.my.domain.tld (1.2.3.4)
> Checking glue for ns1.my.domain.tld (1234::1).
> Missing glue at child: ns1.my.domain.tld
> Checking glue for ns2.my.domain.tld (1.2.3.4).
> Child glue for bgwe.eu found: ns2.my.domain.tld (1.2.3.4)
> Checking glue for ns2.my.domain.tld (1234::1).
> Missing glue at child: ns2.my.domain.tld

I'm not very familiar with Python and DNS, please verify ;)
2014-07-18 13:03:09 +02:00
Joshua Tauberer 42c891032d don't create a www. subdomain on any domains that are themselves subdomains within a zone, i.e. don't create www.PUBLIC_HOSTNAME if PUBLIC_HOSTNAME is a subdomain of another domain, which is what we normally recommend 2014-07-17 13:08:05 +00:00
Joshua Tauberer d7a9e7cc17 run management/dns_update.py from the console to dump the DNS records, with explanations, in case the user wants to host DNS off of the box 2014-07-17 13:08:05 +00:00
Joshua Tauberer 7803ac9ca4 write explanatory text as we build DNS zones so we can help the user manage DNS off of the box 2014-07-17 13:08:05 +00:00
Joshua Tauberer eac349187d whats_next: move the admin alias check to the system section 2014-07-16 09:36:56 -04:00
Joshua Tauberer 9c7d476915 re-do catch-all aliases, fixes #107 (originally #104)
This reverts pull request #105 from jonessen96/master (84d2023f94) which was incorrect because it lost the "+" in DOT_ATOM_TEXT and so was not accepting any email addresses.

Am taking the opportunity to make the code cleaner while I'm here.
2014-07-13 12:29:43 +00:00
Jonas Platte c35252720f Prohibited usage of empty local part for validate_email(email, strict = true) 2014-07-12 22:57:38 +02:00
Jonas Platte 70e4e7f7be Fixed validate_email not accepting catchalls (empty local part of the address) 2014-07-12 03:22:55 +02:00
Joshua Tauberer 85bd2c8804 use the Dovecot managesieve service to manage sieve scripts
This lets roundcube's manageseive plugin do cool things like vacation responses.

Also:

* Run the spam filtering sieve script out of a global sieve file that we'll place in /etc/dovecot. It is no longer necessary to create per-user sieve files for this. Remove them with a new migration. Remove the code that created them.

* Corrects the spam script. Backslashes were double-escaped probably because this script started embedded within the bash script. Not sure how this was working until now.

this adapts work by @h8h in #103
2014-07-10 23:09:07 +00:00
Joshua Tauberer 41b3df6d78 manage hostmaster@ and postmaster@ automatically, create administrator@ during setup instead
closes #94
2014-07-09 19:30:17 +00:00
Joshua Tauberer 22a010ecb9 say that certificates are valid too in output 2014-07-09 16:38:56 +00:00
Joshua Tauberer 659b5c8aa3 if the server certificate can be used for a non-primary domain, use it 2014-07-09 16:38:42 +00:00
Joshua Tauberer 6c70b10c15 tell users to restart nginx after plugging in a new cert 2014-07-09 14:05:59 +00:00
Joshua Tauberer deebda06e1 utils.sort_domains wasn't right 2014-07-09 12:35:12 +00:00
Joshua Tauberer 1a74b81f44 new nginx configuration yaml file to allow proxying of whole domains elsewhere 2014-07-09 12:31:32 +00:00
Joshua Tauberer 04e30ffa78 check that the installed certificate corresponds to the private key 2014-07-08 15:47:54 +00:00
Joshua Tauberer 59a9d02fa5 check that installed certificates are for the domains we are using the certificates for 2014-07-07 12:06:11 +00:00
Joshua Tauberer 65fb65ada7 an mx record may be missing if the A record matches the A record of PRIMARY_HOSTNAME 2014-07-07 02:35:45 +00:00
Joshua Tauberer 28e254fb84 whats_next: Allow the PRIMARY_HOSTNAME to not have an MX because the default value means the domain itself, which is what we want anyway 2014-07-07 02:35:45 +00:00
Joshua Tauberer e898cd5d2a whats_next: wrap output to the actual width of the terminal 2014-07-07 02:35:45 +00:00
Joshua Tauberer 6a231d4409 clarify that an SSL cert can remain self-signed on the non-primary domains if the domain isn't being used for web 2014-07-07 02:35:45 +00:00
Joshua Tauberer 49d5561933 when adding/removing mail addresses also update nginx's config 2014-07-06 12:16:50 +00:00
Joshua Tauberer c8856f107d migrate the SSL certificates path for non-primary certs to a new layout using a new migration script 2014-06-30 20:41:29 +00:00
Joshua Tauberer 06ba25151f get_domain_ssl_files returned the wrong path for the CSR for PRIMARY_HOSTNAME 2014-06-30 19:49:41 +00:00
Joshua Tauberer b5aa1b0f31 walk the user through choosing the PRIMARY_HOSTNAME by first asking for their email address 2014-06-30 10:20:58 -04:00
Joshua Tauberer fed5959288 s/PUBLIC_HOSTNAME/PRIMARY_HOSTNAME/ throughout 2014-06-30 09:15:36 -04:00
Joshua Tauberer 87f001a5d5 some comments 2014-06-24 03:24:41 +00:00
Joshua Tauberer 1dec8c65ce move the SSH password login check into whats_next.py (it used to be in start.sh and then moved to an unused script when it became a problem for Vagrant) 2014-06-23 19:39:20 +00:00
Joshua Tauberer d4ce50de86 new tool to purchase and install a SSL certificate using Gandi.net's API 2014-06-23 10:53:29 +00:00
Joshua Tauberer 30c416ff6e rename the new checklist script to whats_next.py 2014-06-23 00:11:24 +00:00
Joshua Tauberer 5aa09c3f9b let the user override some DNS records in a different way
Moved the configuration to a single YAML file, rather than one per domain, to be clearer.

re-does 33f06f29c1
2014-06-22 19:33:30 +00:00
Joshua Tauberer 343886d818 add mail alias checks and other cleanup 2014-06-22 16:28:55 +00:00
Joshua Tauberer deab8974ec if we handle mail for both a domain and any subdomain, only create a zone for the domain and put the subdomain's DNS records in the main domain's zone file 2014-06-22 16:24:15 +00:00
Joshua Tauberer 4668367420 first pass at a management tool for checking what the user must do to finish his configuration: set NS records, DS records, sign his certificates, etc. 2014-06-22 15:54:22 +00:00
Michael Kropat 9e63ec62fb Cleanup: remove env dependency 2014-06-22 08:55:19 -04:00
Michael Kropat d100a790a0 Remove API_KEY_FILE setting 2014-06-22 08:45:29 -04:00
Michael Kropat 554a28479f Merge remote-tracking branch 'upstream/master' into mgmt-auth
Conflicts:
	management/daemon.py
2014-06-21 21:29:25 -04:00
Joshua Tauberer 064d75e261 Merge pull request #73 from mkropat/syslog-logging
Tell Flask to log to syslog
2014-06-21 21:22:27 -04:00
Michael Kropat 067052d4ea Add key-based authentication to management service
Intended to be the simplest auth possible: every time the service
starts, a random key is written to `/var/lib/mailinabox/api.key`. In
order to authenticate to the service, the client must pass the contents
of `api.key` in an HTTP basic auth header. In this way, users who do not
have read access to that file are not able to communicate with the
service.
2014-06-21 23:42:48 +00:00
Michael Kropat 53e15eae15 Tell Flask to log to syslog
- Writes Flask warnings and errors to `/var/log/syslog`
- Helps to debug issues when running in production
2014-06-21 23:25:35 +00:00
Joshua Tauberer 67d31ed998 move the SSL setup into its own bash script since it is used for much more than email now 2014-06-21 22:16:46 +00:00
Joshua Tauberer 5faa1cae71 manage the nginx conf in the management daemon too so we can have nginx operate on all domains that we serve mail for 2014-06-20 01:55:12 +00:00
Joshua Tauberer 126ea94ccf drop support for ADSP which since last November is no longer recommended per http://datatracker.ietf.org/doc/status-change-adsp-rfc5617-to-historic/ 2014-06-18 22:56:55 -04:00
Joshua Tauberer 95e61bc110 add DANE TLSA records to the PUBLIC_HOSTNAME's DNS
Postfix has a tls_security_level called "dane" which uses DNS-Based Authentication of Named Entities (DANE)
to require, if specified in the DNS of the MX host, an encrpyted connection with a known certificate.

This commit adds TLSA records.
2014-06-19 01:39:27 +00:00
Joshua Tauberer 699bccad80 missing spaces in nsd.conf (has no effect but looks proper) 2014-06-18 23:53:52 +00:00
Joshua Tauberer afb6c26c8b run bind9 on the loopback interface for ensuring we are using a DNSSEC-aware nameserver to resolve our own DNS queries (i.e. when sending mail) since we can't trust that the network configuration provided for us gives us a DNSSEC-aware DNS server
see #71
2014-06-18 19:45:47 -04:00
Joshua Tauberer 761fac729b nsd.conf wasn't properly using the signed zone files 2014-06-18 23:30:35 +00:00
Joshua Tauberer dd15bf4384 use a better sort order for records in DNS zone files 2014-06-17 23:34:06 +00:00
Joshua Tauberer 14396e58f8 dont create a separate zone for PUBLIC_HOSTNAME if it is a subdomain of another zone (hmm, this is a general principle that could apply to any two domains the box is serving) 2014-06-17 23:30:00 +00:00
Joshua Tauberer 33f06f29c1 let the user override some DNS records 2014-06-17 22:21:51 +00:00
Joshua Tauberer 88709506f8 add DNSSEC
* sign zones
* in a cron job, periodically re-sign zones because they expire (not tested)
2014-06-17 22:21:12 +00:00
Joshua Tauberer aaa735dbfe write nsd.conf zones in a predictable order so that we don't keep rewriting it 2014-06-12 22:28:37 -04:00
Joshua Tauberer e9cde52a48 two more cases of shelling out external programs in a more secure way, see cecda9cec5 2014-06-12 21:06:04 -04:00
Joshua Tauberer 8bd62aa3bc increase duplicity's volume size from the default of 25MB to 100MB so we create fewer files 2014-06-09 13:47:41 +00:00
Joshua Tauberer 5490142df5 re-do the backup script to use the duplicity program
Duplicity will manage the process of creating incremental backups for us.
Although duplicity can both encrypt & copy files to a remote host, I really
don't like PGP and so I don't want to use that.

Instead, we'll back up to a local directory unencrypted, then manually
encrypt the full & incremental backup files. Synchronizing the encrypted
backup directory to a remote host is a TODO.
2014-06-09 09:34:52 -04:00
Joshua Tauberer cecda9cec5 management: shell out external programs in a more secure way 2014-06-09 08:09:45 -04:00
Michael Kropat ae67409603 Support dual-stack IPv4/IPv6 mail servers
Addresses #3

Added support by adding parallel code wherever `$PUBLIC_IP` was used.
Providing an IPv6 address is completely optional.

Playing around on my IPv6-enabled mail server revealed that — before
this change — mailinabox might try to use an IPv6 address as the value
for `$PUBLIC_IP`, which wouldn't work out well.
2014-06-08 18:32:52 -04:00
Joshua Tauberer 242cadebc8 allow dashes in emails during validation, and for aliases allow a much wider range of characters, fixes #64
* for local mail users, also disallows periods at the beginning or end of the local or domain parts
* Dovecot gets confused if the string contains any unusual characters, so local mail users are restricted to a narrow regex
* for mail aliases Postfix is not confused so use a regex based on RFC 2822
2014-06-06 10:51:36 -04:00
Joshua Tauberer f1dac1fe13 show less output when updating DNS configuration 2014-06-06 10:51:36 -04:00
Joshua Tauberer 6194c63f76 add management comments for checking for updated Ubuntu packages and applying updates 2014-06-05 20:57:30 +00:00
Joshua Tauberer 295981828f Vagrantize
* adding a Vagrantfile
* in a non-interactive setup like this, create the user's first email account for them
* let the machine auto-detect its IP address using http://icanhazip.com/
* use our own justtesting.email domain to provision a subdomain for users so they can quickly get started
2014-06-04 19:39:58 -04:00
Joshua Tauberer 7fa4862f1a refactor dns_update so that the zone is first generated in a file-format agnostic way 2014-06-04 19:00:31 -04:00
Joshua Tauberer 8ed15168c0 the new dns_update totally forgot to write the OpenDKIM tables 2014-06-04 18:44:13 -04:00
Joshua Tauberer 89730bd643 new backup script, see #11 2014-06-03 21:16:38 +00:00
Joshua Tauberer c54b0cbefc move management into a daemon service running as root
* Created a new Python/flask-based management daemon.
* Moved the mail user management core code from tools/mail.py to the new daemon.
* tools/mail.py is a wrapper around the daemon and can be run as a non-root user.
* Adding a new initscript for the management daemon.
* Moving dns_update.sh to the management daemon, called via curl'ing the daemon's API.

This also now runs the DNS update after mail users and aliases are added/removed,
which sets up new domains' DNS as needed.
2014-06-03 13:56:40 +00:00