Compare commits

...

1644 Commits

Author SHA1 Message Date
Girish Ramakrishnan
36a21acae8 skip verification for prereleases because we remove it from release.json 2018-08-06 16:23:23 -07:00
Girish Ramakrishnan
1ed4710c68 Better error message 2018-08-05 23:38:49 -07:00
Girish Ramakrishnan
75b6688734 Clear timeout when setting backup config 2018-08-05 22:29:27 -07:00
Girish Ramakrishnan
f7a7e4e95a Fix text in account setup screen 2018-08-05 21:58:07 -07:00
Girish Ramakrishnan
a8ba0b91f7 Allow subdomain in the location field
This allows one to easily add "dev.staging@domain.com" etc without having to create
yet another domain. This plays well with the concept that we have a
mail domain for every domain. So we get mails from @domain.com working for
these subdomain installations.
2018-08-04 09:37:18 -07:00
Girish Ramakrishnan
95540e8cbc Do ownership check in exec route 2018-08-03 22:19:42 -07:00
Girish Ramakrishnan
9ebd22d6f7 add api note 2018-08-03 22:19:36 -07:00
Girish Ramakrishnan
1cf5807fb9 Send spaces config in config route
This is here because normal users cannot access settings route
2018-08-03 18:26:16 -07:00
Girish Ramakrishnan
cc7824681b Return ownerId in apps response 2018-08-03 18:15:22 -07:00
Girish Ramakrishnan
a0a523ae71 spaces: verify app ownership in app management routes 2018-08-03 17:35:58 -07:00
Girish Ramakrishnan
fba70d888b Remove tokenScopes
decided that the UI won't use this any more and will just the admin flag
2018-08-03 10:07:23 -07:00
Girish Ramakrishnan
ce9fc7b3f7 Better error message 2018-08-03 09:46:22 -07:00
Girish Ramakrishnan
3d4df8e26c Add test for spaces config 2018-08-03 09:46:16 -07:00
Girish Ramakrishnan
d3f9647cd5 Add settings for Spaces 2018-08-03 09:40:57 -07:00
Girish Ramakrishnan
2a49569805 Send admin flag in the profile 2018-08-03 09:34:25 -07:00
Girish Ramakrishnan
47c8700d42 make scopesForUser async 2018-08-03 09:34:19 -07:00
Girish Ramakrishnan
d302dbc634 Fix tests 2018-08-02 14:59:50 -07:00
Girish Ramakrishnan
eab3cd6b2b ownerId for domains is not implemented yet 2018-08-01 18:53:49 -07:00
Girish Ramakrishnan
92151b1e42 Add note on npm rebuild 2018-08-01 18:37:40 -07:00
Girish Ramakrishnan
621d00a5c6 GPG verify releases
Part of #189
2018-08-01 17:16:42 -07:00
Girish Ramakrishnan
5bd7cd6749 Check if syslog binary exists first
The command fails in a subshell and strange things happen

==> installer: update cloudron-syslog
/tmp/box-src-hotfix/scripts/installer.sh: line 99: /usr/local/cloudron-syslog/bin/cloudron-syslog: No such file or directory
/tmp/box-src-hotfix/scripts/installer.sh: line 99: : command not found
2018-08-01 12:18:56 -07:00
Girish Ramakrishnan
5fb525f011 Commit binary public key
GPG's --verify option can only use binary format
2018-07-31 20:25:46 -07:00
Girish Ramakrishnan
d8257c4745 refactor updater logic into updater.js 2018-07-31 20:20:10 -07:00
Girish Ramakrishnan
ef5dc7311f Do not encrypt empty path 2018-07-31 19:41:03 -07:00
Girish Ramakrishnan
498642b670 Fix debugs 2018-07-31 19:32:56 -07:00
Girish Ramakrishnan
daa8514654 Pass the message and not error object 2018-07-31 10:46:35 -07:00
Girish Ramakrishnan
608de479fb Add releases public key
Part of #189
2018-07-31 10:34:01 -07:00
Johannes Zellner
51f7a47ea6 Fix db migration script 2018-07-30 22:58:09 +02:00
Girish Ramakrishnan
480aed9f33 Update mail addon 2018-07-30 12:37:37 -07:00
Girish Ramakrishnan
74ae0a1787 More changes 2018-07-30 10:46:14 -07:00
Girish Ramakrishnan
ed8351b0dc Add re-installation check
Fixes #536
2018-07-30 10:10:30 -07:00
Girish Ramakrishnan
a1070b7da3 storage: fix file not found message 2018-07-30 07:47:52 -07:00
Girish Ramakrishnan
3067d87ca9 handle decryption errors 2018-07-29 21:01:20 -07:00
Girish Ramakrishnan
56ca6f449f Set any restore errors in status object
Fixes #505
2018-07-29 20:31:58 -07:00
Girish Ramakrishnan
99ad3e499d s3: do not rely on entry.s3 2018-07-29 09:00:57 -07:00
Girish Ramakrishnan
7182ad4205 s3: Remove usage of entries.s3 2018-07-29 07:51:12 -07:00
Girish Ramakrishnan
0b10e2b332 s3: add listDir
Fixes #440
2018-07-28 09:05:44 -07:00
Girish Ramakrishnan
f546d53ca2 gcs: add listDir
part of #440
2018-07-28 03:51:32 -07:00
Girish Ramakrishnan
2bcc0eef96 fs: downloadDir is unused 2018-07-27 16:56:30 -07:00
Girish Ramakrishnan
a5daad2e1a rsync: encrypted download (fs backend)
Part of #440
2018-07-27 16:06:13 -07:00
Girish Ramakrishnan
b3c8767d79 rsync: encrypted upload (fs backend)
Part of #440
2018-07-27 15:34:48 -07:00
Girish Ramakrishnan
f97f528f05 backup: Implement downloadDir using listDir 2018-07-27 15:24:35 -07:00
Girish Ramakrishnan
ba8a549235 fs: open the source stream using download() 2018-07-27 15:23:48 -07:00
Girish Ramakrishnan
737541f707 storage: standardize the listDir API 2018-07-27 15:23:26 -07:00
Girish Ramakrishnan
94cb222869 filesystem: Use listDir
We can now refactor all the iterating/fs write logic into backups.js
(required for restoring encrypted backups)
2018-07-27 14:09:52 -07:00
Girish Ramakrishnan
df98847535 Remove backupDone from storage interface
This is only used by caas
2018-07-27 12:08:19 -07:00
Girish Ramakrishnan
3d22458f9b Add the 3.0 UI changes 2018-07-27 00:08:08 -07:00
Girish Ramakrishnan
d76381fa26 More 3.0 changes 2018-07-27 00:04:31 -07:00
Girish Ramakrishnan
606cd4da36 Allow - in mailbox names (for no-reply) 2018-07-26 23:48:21 -07:00
Girish Ramakrishnan
554006683e Only unset of admin flag is disallowed 2018-07-26 23:43:44 -07:00
Girish Ramakrishnan
0966edd8fe Fix missing require 2018-07-26 22:36:20 -07:00
Girish Ramakrishnan
78a2176d1d Make admin simply a boolean instead of group
This simplifies a lot of logic. Keeping an admin group has no benefit
2018-07-26 22:29:57 -07:00
Girish Ramakrishnan
39848a25a8 Refactor a bit 2018-07-26 15:35:41 -07:00
Girish Ramakrishnan
ea946396e7 Use users.isAdmin in all places 2018-07-26 13:23:06 -07:00
Girish Ramakrishnan
b4d5def56d Revert role support 2018-07-26 13:23:06 -07:00
Johannes Zellner
477abf53f3 Add initial 3.0.0 changes 2018-07-26 21:36:43 +02:00
Girish Ramakrishnan
0cb03e3789 Add REST route for platform config
Fixes #566
2018-07-25 14:09:15 -07:00
Girish Ramakrishnan
f4d7d4e7f2 Set the domain field 2018-07-25 11:41:42 -07:00
Girish Ramakrishnan
c09ae963e9 merge set/addDnsRecords
This also makes the update mail domain route redundant
2018-07-25 10:51:21 -07:00
Girish Ramakrishnan
fa30312cea lint 2018-07-25 10:34:57 -07:00
Girish Ramakrishnan
c063267c72 Split setting of dns records from mail config route
This allows us to enable email server but not setup the dns records
yet. Useful for importing existing mailboxes from another server
without adjusting the DNS.
2018-07-25 10:29:28 -07:00
Girish Ramakrishnan
589602cdb0 Add note 2018-07-25 08:29:39 -07:00
Girish Ramakrishnan
6be062f8fd Return empty object for angular 2018-07-24 22:19:34 -07:00
Girish Ramakrishnan
837ec4eb12 Send subdomain field in mail status 2018-07-24 14:25:21 -07:00
Girish Ramakrishnan
4a4166764a relay: Add a connect timeout 2018-07-23 17:05:15 -07:00
Girish Ramakrishnan
7654f36e23 Do temporary redirect instead
Permanent redirect can be cached forever in the browser which
means that changing redirect settings appear to not work.
2018-07-15 17:43:36 -07:00
Girish Ramakrishnan
6810c61e58 Add audit event for ownership transfer 2018-07-05 13:51:22 -07:00
Johannes Zellner
75f9b19db2 Ensure we uri encode the email query arguments for invite, reset and setup links 2018-07-04 11:09:29 +02:00
Johannes Zellner
17410c9432 Remove notes about updates only on paid plan for the digest 2018-07-04 10:59:17 +02:00
Johannes Zellner
8a1de81284 Cleanup sysadmin backup trigger test to only test for backup start event 2018-06-30 14:33:51 +02:00
Johannes Zellner
7b540a1d2d Fixup database tests 2018-06-30 14:12:35 +02:00
Johannes Zellner
8e8488a8e6 Lets be explicit about the error 2018-06-30 14:02:40 +02:00
Johannes Zellner
b1b843fdd8 Fix dns tests 2018-06-30 13:59:23 +02:00
Johannes Zellner
c13c4d0b28 Ensure we purge all nginx configs of an app 2018-06-29 23:14:06 +02:00
Johannes Zellner
2371c8053f We have added a query for removing subdomains in the transaction 2018-06-29 23:14:06 +02:00
Johannes Zellner
7dc2f3cb5b Also wait for alternateDomains to be in sync 2018-06-29 23:14:06 +02:00
Johannes Zellner
163563f400 Remove now unused dnsRecordId 2018-06-29 23:14:06 +02:00
Johannes Zellner
868ed977b3 Cleanup alternateDomain dns records and nginx config 2018-06-29 23:14:06 +02:00
Johannes Zellner
262fe18fb2 Set dns record id for alternateDomains 2018-06-29 23:14:06 +02:00
Johannes Zellner
1eba79660e Move dnsRecordId to subdomains table 2018-06-29 23:14:06 +02:00
Johannes Zellner
3088ac098f Put redirect label into alternateDomain nginx configs 2018-06-29 23:14:06 +02:00
Johannes Zellner
45a41ea161 Fix typo 2018-06-29 23:14:06 +02:00
Johannes Zellner
6c17709d2a Fix fqdn building for alternateDomains 2018-06-29 23:14:06 +02:00
Johannes Zellner
2a52543087 The property is called subdomain not location 2018-06-29 23:14:06 +02:00
Johannes Zellner
f4f6f4e7e0 Use business logic for getting all apps in taskmanager 2018-06-29 23:14:06 +02:00
Johannes Zellner
f53c526677 Remove superflous . for user cert key file location 2018-06-29 23:14:06 +02:00
Johannes Zellner
1aa58a3905 ignore alternateDomains field for appdb updates 2018-06-29 23:14:06 +02:00
Johannes Zellner
2d58a6bdff Fix typo 2018-06-29 23:14:06 +02:00
Johannes Zellner
40c22a1ad7 send alternateDomains over the wire 2018-06-29 23:14:06 +02:00
Johannes Zellner
3d0da34960 Create nginx configs for app redirects 2018-06-29 23:14:06 +02:00
Johannes Zellner
a6e53e3617 Ensure certificates for alternateDomains 2018-06-29 23:14:06 +02:00
Johannes Zellner
8efab41d37 Amend the alternateDomains property to app objects 2018-06-29 23:14:06 +02:00
Johannes Zellner
9af456cc7d Fix appdb.add as location and domain columns are gone 2018-06-29 23:14:06 +02:00
Johannes Zellner
9ba78b5b87 Setup alternate domains in apptask configure 2018-06-29 23:14:06 +02:00
Johannes Zellner
b1b848de21 Support configuring alternateDomains for apps 2018-06-29 23:14:06 +02:00
Johannes Zellner
5497a7d4d8 Do not handle location and domain field for apps table updates 2018-06-29 23:14:06 +02:00
Johannes Zellner
18887b27e6 Fix migration script typo 2018-06-29 23:14:06 +02:00
Johannes Zellner
fb42b54210 Remove apps.location and apps.domain
This is now managed in the subdomains table
2018-06-29 23:14:06 +02:00
Johannes Zellner
4d2ba2adaa Use subdomains table in appdb 2018-06-29 23:14:06 +02:00
Johannes Zellner
c97e8d6bd4 add subdomains table with migration scripts 2018-06-29 23:14:06 +02:00
Girish Ramakrishnan
b15029de11 Send tokenScopes as an array 2018-06-29 09:53:12 -07:00
Girish Ramakrishnan
9aa74c99fc Make setup route return tokenScopes
This is used by the dashboard logic during initial activation
2018-06-29 08:27:34 -07:00
Girish Ramakrishnan
35c9e99102 Move the update info into separate route (since it is sensitive) 2018-06-28 17:50:27 -07:00
Girish Ramakrishnan
cab9bc3a61 Unify the config routes into /api/v1/config
No more separate config routes for different types of user
2018-06-28 17:40:57 -07:00
Girish Ramakrishnan
712c920b86 Move caas config to separate route 2018-06-28 17:28:46 -07:00
Girish Ramakrishnan
9978dff627 Add API to set and transfer ownership 2018-06-28 16:48:04 -07:00
Girish Ramakrishnan
ff5bd42bef remove mostly dead comment 2018-06-28 14:19:56 -07:00
Girish Ramakrishnan
dfa318e898 Add ownerId for apps
This tracks who installed the app.
2018-06-28 14:13:12 -07:00
Girish Ramakrishnan
38977858aa When issuing token intersect with the existing user roles
Also:
* Move token validation to accesscontrol.js
* Use clients.addTokenByUserId everywhere
2018-06-28 00:07:43 -07:00
Girish Ramakrishnan
6510240c0a Fix accesscontrol.intersectScopes 2018-06-27 18:08:38 -07:00
Girish Ramakrishnan
d66dc11f01 Make canonicalScopeString return sorted array 2018-06-27 14:07:25 -07:00
Girish Ramakrishnan
ce4424d115 debug out the scope 2018-06-27 13:54:10 -07:00
Girish Ramakrishnan
a958c01974 digest: drop the Cloudron prefix in the subject 2018-06-27 11:00:41 -07:00
Girish Ramakrishnan
877f181f8d Put ts in app listing as well 2018-06-26 19:58:21 -07:00
Girish Ramakrishnan
02c0137dc1 Add a timestamp column to apps table
this field can be used in UI to see if more detailed app information
has to be fetched (since it calls the list apps REST API periodically)
2018-06-26 18:16:39 -07:00
Girish Ramakrishnan
d0b34cc43e Fix schema 2018-06-26 18:05:34 -07:00
Girish Ramakrishnan
93a2cab355 Ignore internal mailbox conflict errors 2018-06-26 17:44:14 -07:00
Girish Ramakrishnan
6907475f7a Add app management scope
This splits the apps API into those who have just 'read' access
and those who have 'manage' access.
2018-06-26 08:56:30 -07:00
Girish Ramakrishnan
9bf93b026b rename to removeInternalFields 2018-06-25 16:40:16 -07:00
Girish Ramakrishnan
f932f8b3d3 Add user management scope
This splits the user and groups API into those who have just 'read' access
and those who have 'manage' access.
2018-06-25 16:10:00 -07:00
Girish Ramakrishnan
7ab5d5e50d Add domain management scope
This splits the domains API into those who have just 'read' access
(i.e without configuration details) and those who have 'manage' access.
2018-06-25 15:12:22 -07:00
Johannes Zellner
5028230354 Update cloudron-syslog
Fixes #564
2018-06-25 19:35:13 +02:00
Girish Ramakrishnan
80e9214f5b Reduce password length for sendmail/recvmail
Fixes #565
2018-06-22 16:37:34 -07:00
Girish Ramakrishnan
5ca64dd642 Normalize host path to prevent access to arbitrary paths 2018-06-22 08:29:08 -07:00
Girish Ramakrishnan
24d9d3063b Allow specifying bindMounts array to localstorage addon 2018-06-21 22:04:06 -07:00
Girish Ramakrishnan
74b1df17c0 Fix groups test and route to make name optional 2018-06-20 09:31:50 -07:00
Girish Ramakrishnan
7880a2f9c3 API returns 403 for incorrect password 2018-06-20 09:27:24 -07:00
Girish Ramakrishnan
8a84872704 Wrong password logs out the user 2018-06-18 18:52:35 -07:00
Girish Ramakrishnan
5d13cc363f Allow group name to be changed 2018-06-18 18:30:40 -07:00
Girish Ramakrishnan
987a42b448 Fix syntax 2018-06-18 17:58:35 -07:00
Girish Ramakrishnan
3601e4f8a6 if -> while 2018-06-18 17:39:15 -07:00
Girish Ramakrishnan
60ed290179 validate role names against existing roles 2018-06-18 17:32:07 -07:00
Girish Ramakrishnan
ff73bc121f Make tokenScope plural 2018-06-18 15:10:02 -07:00
Girish Ramakrishnan
6cd0601629 Map group roles to scopes 2018-06-18 14:52:39 -07:00
Girish Ramakrishnan
b5c8e7a52a Rename to getGroups 2018-06-18 14:10:29 -07:00
Girish Ramakrishnan
7f3114e67d Rename to get/setMembership (to indicate IDs and not group objects 2018-06-18 13:57:17 -07:00
Girish Ramakrishnan
1dbcf2a46a Rename to groups.update 2018-06-18 13:41:27 -07:00
Girish Ramakrishnan
898cbd01b3 tokens table always has canonical scope 2018-06-17 23:11:36 -07:00
Girish Ramakrishnan
b6b7d08af3 Rename to accesscontrol.canonicalScopeString 2018-06-17 22:43:42 -07:00
Girish Ramakrishnan
6a2dacb08a Make intersectScopes take an array 2018-06-17 22:39:33 -07:00
Girish Ramakrishnan
1015b0ad9c validateScope -> validateScopeString 2018-06-17 22:29:17 -07:00
Girish Ramakrishnan
106e17f7ff caas: verify dns config
this is so that it fails if someone gives invalid token via API call
2018-06-17 22:22:05 -07:00
Girish Ramakrishnan
6ca28d9a58 validate dns config parameters 2018-06-17 22:21:51 -07:00
Girish Ramakrishnan
ad6bc191f9 Make hasScopes take an array 2018-06-17 21:06:17 -07:00
Girish Ramakrishnan
682f7a710c Add an appstore scope for subscription settings 2018-06-17 18:09:13 -07:00
Girish Ramakrishnan
f24a099e79 Remove user.admin property
The UI will now base itself entirely off the scopes of the token
2018-06-17 16:49:56 -07:00
Girish Ramakrishnan
156ffb40c9 Remove scope from users.get 2018-06-17 16:07:20 -07:00
Girish Ramakrishnan
db8b6838bb Move skip password verification logic to accesscontrol.js 2018-06-17 15:20:27 -07:00
Girish Ramakrishnan
c3631350cf We can skip user.scope here since we will intersect at access time anyway 2018-06-17 15:11:10 -07:00
Girish Ramakrishnan
669a1498aa Do not dump token in logs 2018-06-17 15:01:42 -07:00
Girish Ramakrishnan
12e55d1fab Use _.flatten instead 2018-06-16 13:03:52 -07:00
Girish Ramakrishnan
ca9cd2cf0f Add groups.getRoles 2018-06-16 00:29:56 -07:00
Girish Ramakrishnan
e8d9597345 Fix various error codes
401 - bad password/wrong password
403 - authenticated but not authorized
409 - conflict
2018-06-15 23:15:30 -07:00
Girish Ramakrishnan
24b0a96f07 Move passport logic to routes 2018-06-15 17:32:40 -07:00
Girish Ramakrishnan
858ffcec72 Add note 2018-06-15 17:04:18 -07:00
Girish Ramakrishnan
05a8911cca condense the comments 2018-06-15 16:56:35 -07:00
Girish Ramakrishnan
89b41b11a4 Remove bogus accesscontrol logic 2018-06-15 16:26:14 -07:00
Girish Ramakrishnan
491d1c1273 getByResetToken already has the user object 2018-06-15 16:22:28 -07:00
Girish Ramakrishnan
0a0884bf93 lint 2018-06-15 16:10:06 -07:00
Girish Ramakrishnan
a1ac7f2ef9 Remove support for authenticating non-oauth2 clients via BasicStrategy
This is not used anywhere
2018-06-15 15:38:58 -07:00
Girish Ramakrishnan
6aef9213aa Add notes on the various strategies 2018-06-15 15:38:53 -07:00
Girish Ramakrishnan
2e92172794 Do not dump the entire token 2018-06-15 14:56:52 -07:00
Girish Ramakrishnan
c210359046 Create the backup logs dir 2018-06-15 14:56:32 -07:00
Girish Ramakrishnan
042ea081a0 Typo 2018-06-15 14:35:52 -07:00
Girish Ramakrishnan
1c32224a8a Move backup logs to make the REST API work 2018-06-15 09:47:34 -07:00
Johannes Zellner
b3fa5afe3a First show apptask logs, then app logs 2018-06-15 14:58:07 +02:00
Johannes Zellner
843fec9dcb Fix wrong hasSubscription logic for digest email 2018-06-15 13:44:33 +02:00
Johannes Zellner
35d9cc3c02 Update cloudron-syslog 2018-06-15 10:20:03 +02:00
Girish Ramakrishnan
02d5d2f808 Add API to add and update the group roles 2018-06-15 00:28:27 -07:00
Girish Ramakrishnan
a77d45f5de Add rolesJson to groups table
This will contain the roles ('role definition') of a group of
users. We will internally map these to our API scopes.
2018-06-14 22:54:52 -07:00
Girish Ramakrishnan
5e09f3dcb2 Group names can contain - and end with .app
now that we have decoupled it from mailbox names, this restriction
can be removed
2018-06-14 22:22:09 -07:00
Girish Ramakrishnan
eb566d28e7 Remove groupdb._addDefaultGroups
Putting this in db code causes issues when we merge in the
accesscontrol/roles variables (groupdb needs to source those
variables)
2018-06-14 21:56:34 -07:00
Girish Ramakrishnan
8795da5d20 Allow subscopes
We can now have scopes as apps:read, apps:write etc
2018-06-14 20:56:04 -07:00
Girish Ramakrishnan
a9ec46c97e Add test for accesscontrol.validateScope 2018-06-14 20:51:22 -07:00
Girish Ramakrishnan
dc86b0f319 validateRequestedScopes -> hasScopes 2018-06-14 20:31:48 -07:00
Girish Ramakrishnan
f7089c52ff normalizeScope -> intersectScope 2018-06-14 20:23:56 -07:00
Girish Ramakrishnan
62793ca7b3 Add accesscontrol.canonicalScope tests 2018-06-14 20:17:59 -07:00
Girish Ramakrishnan
92e6909567 Move feedback route to cloudronScope 2018-06-14 20:03:51 -07:00
Girish Ramakrishnan
55e5c319fe Fix failing log test 2018-06-14 13:43:44 -07:00
Johannes Zellner
1f8451fedb Do not print tail file headers in the logs 2018-06-14 12:53:49 +02:00
Johannes Zellner
cdc78936b5 Ignore faulty empty log lines 2018-06-14 12:53:19 +02:00
Girish Ramakrishnan
eaf0b4e56e mail api: handle not found errors 2018-06-13 07:51:22 -07:00
Girish Ramakrishnan
7339c37b98 Fix invite link in userAdded notification 2018-06-12 20:08:59 -07:00
Girish Ramakrishnan
3176938ea0 Add 2.4.1 changes 2018-06-12 19:25:24 -07:00
Girish Ramakrishnan
c3c77c5a97 Fix wording 2018-06-12 18:18:41 -07:00
Girish Ramakrishnan
32e6b9024c Add email query param to reset code path
This reduces any attack surface
2018-06-12 17:56:41 -07:00
Girish Ramakrishnan
5a6ea33694 Display apptask logs 2018-06-12 14:55:58 -07:00
Girish Ramakrishnan
60bff95d9f Add journalctl fallback for box logs 2018-06-12 14:39:33 -07:00
Girish Ramakrishnan
0cc2838b8b lint 2018-06-12 13:49:52 -07:00
Girish Ramakrishnan
0fc4f4bbff Explicitly pass port and logdir 2018-06-11 22:53:12 -07:00
Girish Ramakrishnan
0b82146b3e Install cloudron-syslog service file from box repo 2018-06-11 22:42:49 -07:00
Girish Ramakrishnan
4369b3046e Make options non-optional 2018-06-11 15:14:59 -07:00
Girish Ramakrishnan
ac75b60f47 Fix password validation text in setup and reset forms 2018-06-11 14:01:40 -07:00
Girish Ramakrishnan
d752ef5fad Move password generation logic to model code 2018-06-11 13:06:08 -07:00
Girish Ramakrishnan
c099d5d3fa Make password strength be 8 chars
Fixes #434
2018-06-11 12:55:24 -07:00
Girish Ramakrishnan
6534297a5d Remove hat module
It's not been updated for 6 years!
2018-06-11 12:38:29 -07:00
Girish Ramakrishnan
2aa6350c94 Change the function names
We had these because user and mailbox code used to be mixed
2018-06-11 11:43:41 -07:00
Girish Ramakrishnan
8b4a399b8f More changes 2018-06-11 11:43:41 -07:00
Johannes Zellner
177243b7f2 Support new platform/addon log style 2018-06-11 20:09:45 +02:00
Girish Ramakrishnan
c2ca827458 Add 2.4.0 changes 2018-06-11 10:13:48 -07:00
Girish Ramakrishnan
90d7dc893c Fix test 2018-06-11 10:01:54 -07:00
Girish Ramakrishnan
eeaaa95ca3 Put email on free plan 2018-06-09 18:26:00 -07:00
Girish Ramakrishnan
04be582573 make the mailbox name follow the apps new location, if the user did not set it explicitly 2018-06-09 11:05:54 -07:00
Girish Ramakrishnan
0953787559 Fix docker exec terminal resize issue
Fixes #549
2018-06-08 11:44:24 -07:00
Girish Ramakrishnan
3bd8a58ea5 Update docker to 18.03.1 2018-06-08 09:13:46 -07:00
Girish Ramakrishnan
275181824f Not sure why package lock keeps changing 2018-06-07 18:45:30 -07:00
Girish Ramakrishnan
f814ffb14f Update node version 2018-06-07 18:43:52 -07:00
Girish Ramakrishnan
95ae948fce more package lock changes 2018-06-07 18:42:47 -07:00
Girish Ramakrishnan
9debf1f6c6 Update some packages 2018-06-07 18:36:36 -07:00
Girish Ramakrishnan
0e583b5afe Update node to 8.11.2 2018-06-07 17:06:47 -07:00
Girish Ramakrishnan
fa47031a63 cloudron-activate: Set externalDisk to true 2018-06-07 11:38:07 -07:00
Girish Ramakrishnan
7fd1bb8597 backup: Add externalDisk option to fs backend
This merely confirms from the user understands that backups have to
stored on an external disk.
2018-06-07 11:14:13 -07:00
Johannes Zellner
8c5b550caa Explicitly use cloudron-syslog 1.0.0 instead of moving master 2018-06-07 16:38:44 +02:00
Johannes Zellner
3d57c32853 Explicitly send empty object for successful post to avoid angular warnings 2018-06-07 16:10:47 +02:00
Johannes Zellner
898d928dd6 logrotate files under platformdata must be owned by root 2018-06-06 18:45:54 +02:00
Johannes Zellner
c578a048dd Ensure app logrotate file is owned by root 2018-06-06 18:39:52 +02:00
Johannes Zellner
2a475c1199 Add logrotate for app and addon logs 2018-06-06 17:36:48 +02:00
Johannes Zellner
57e195883c Use plain syslog tags to be compatible with the format 2018-06-06 14:09:50 +02:00
Johannes Zellner
f2178d9b81 Setup addons to log to cloudron-syslog 2018-06-06 14:09:50 +02:00
Johannes Zellner
df1ac43f40 Use subshells correctly 2018-06-06 14:09:50 +02:00
Johannes Zellner
39059c627b Add --unsafe-perm for cloudron-syslog installation 2018-06-06 14:09:50 +02:00
Johannes Zellner
d942c77ceb Bump infra version to reconfigure the container 2018-06-06 14:09:50 +02:00
Johannes Zellner
c39240c518 Install cloudron-syslog 2018-06-06 14:09:50 +02:00
Johannes Zellner
fd0e2782d8 Deliver the correct utc timestamp instead of the ISO string 2018-06-06 14:09:50 +02:00
Johannes Zellner
36aaa0406e Fix comment about firewall rule setup 2018-06-06 14:09:50 +02:00
Johannes Zellner
17ecb366af Bring back json log format for now 2018-06-06 14:09:50 +02:00
Johannes Zellner
1a83281e16 use port 2514 for syslog 2018-06-06 14:09:50 +02:00
Johannes Zellner
ec41e0eef5 Use tail instead of journalctl to deliver logs 2018-06-06 14:09:50 +02:00
Johannes Zellner
d4097ed4e0 Move logs into platformdata/logs 2018-06-06 14:09:50 +02:00
Johannes Zellner
8fa99fae1a Put all apptask logs of an app in the same log file 2018-06-06 14:09:50 +02:00
Johannes Zellner
e9400e5dce support test usecase to not put logs in /var/log 2018-06-06 14:09:50 +02:00
Johannes Zellner
372a17dc37 Cleanup logs on app uninstall 2018-06-06 14:09:50 +02:00
Johannes Zellner
5ca60b2d3c Since we use log files now, lets keep the apptask timestamp for debug() 2018-06-06 14:09:50 +02:00
Johannes Zellner
1dc649b7a2 Put apptask logs alongside the app logs 2018-06-06 14:09:50 +02:00
Johannes Zellner
74437db740 Use syslog logging backend for apps and addons 2018-06-06 14:09:50 +02:00
Girish Ramakrishnan
70128458b2 Fix crash when renewAll is called when cloudron is not setup yet 2018-06-05 21:27:32 -07:00
Girish Ramakrishnan
900225957e typo: code should return SetupError 2018-06-05 21:19:47 -07:00
Girish Ramakrishnan
fd8f5e3c71 Return error for trailing dot instead 2018-06-05 21:09:07 -07:00
Girish Ramakrishnan
7382ea2b04 Handle my subdomain already existing 2018-06-05 20:53:28 -07:00
Girish Ramakrishnan
09163b8a2b strip any trailing dot in the domain and zoneName 2018-06-05 20:33:14 -07:00
Girish Ramakrishnan
953398c427 lint 2018-06-05 20:02:47 -07:00
Girish Ramakrishnan
9f7406c235 cloudron-activate: Add option to setup backup dir 2018-06-05 19:40:46 -07:00
Girish Ramakrishnan
2e427aa60e Add 2.3.2 changes 2018-06-05 09:51:56 -07:00
Girish Ramakrishnan
ab80cc9ea1 Add username to the TOTP secret name
This works around issue in FreeOTP app which crashed when
the same name is used.

https://github.com/freeotp/freeotp-ios/issues/69
https://github.com/freeotp/freeotp-android/issues/69
2018-06-04 16:08:03 -07:00
Girish Ramakrishnan
321f11c644 mysql: _ prefix is hardcoded in mysql addon already
Fixes #560
2018-06-04 12:31:40 -07:00
Girish Ramakrishnan
47f85434db cloudron-activate: always login since activate return token and not accessToken 2018-06-01 00:12:19 -07:00
Girish Ramakrishnan
7717c7b1cd Add cloudron-activate script to automate activation from VM image 2018-05-31 23:46:44 -07:00
Johannes Zellner
7618aa786c Handle AppstoreError properly when no appstore account was set 2018-05-30 20:33:58 +02:00
Girish Ramakrishnan
f752cb368c Remove spamcannibal
Fixes #559
2018-05-30 11:07:17 -07:00
Girish Ramakrishnan
ca500e2165 mailer: do not send notifications to fallback email 2018-05-30 09:26:59 -07:00
Johannes Zellner
371f81b980 Add test for mail enabling without a subscription 2018-05-30 00:02:18 +02:00
Johannes Zellner
c68cca9a54 Fixup mail test, which requires a subscription 2018-05-29 23:59:53 +02:00
Johannes Zellner
9194be06c3 Fix app purchase test 2018-05-29 23:24:08 +02:00
Johannes Zellner
9eb58cdfe5 Check for plan when enabling email 2018-05-29 13:31:43 +02:00
Johannes Zellner
99be89012d No need to check for active subscription state, as the appstore already does this 2018-05-29 13:31:43 +02:00
Johannes Zellner
541fabcb2e Add convenience function to determine if subscription is 'free' or not 2018-05-29 13:31:43 +02:00
Johannes Zellner
915e04eb08 We do not have an 'undecided' plan state anymore 2018-05-29 13:31:43 +02:00
Girish Ramakrishnan
48896d4e50 more changes 2018-05-28 10:06:46 -07:00
Johannes Zellner
29682c0944 Only allow max of 2 apps on the free plan 2018-05-26 18:53:20 +02:00
Girish Ramakrishnan
346b1cb91c more changes 2018-05-26 08:11:19 -07:00
Girish Ramakrishnan
e552821c01 Add 2.3.1 changes 2018-05-25 11:44:04 -07:00
Girish Ramakrishnan
bac3ba101e Add mailboxName to app configure route
Fixes #558
2018-05-24 16:26:34 -07:00
Girish Ramakrishnan
87c46fe3ea apps: return mailbox name as part of app
part of cloudron/box#558
2018-05-24 15:50:46 -07:00
Girish Ramakrishnan
f9763b1ad3 namecom: MX record not set properly 2018-05-24 09:41:52 -07:00
Girish Ramakrishnan
f1e6116b83 Fix copyright years 2018-05-23 20:02:33 -07:00
Girish Ramakrishnan
273948c3c7 Fix tests 2018-05-22 13:22:48 -07:00
Girish Ramakrishnan
9c073e7bee Preserve addons credentials when restoring 2018-05-22 13:07:58 -07:00
Girish Ramakrishnan
8b3edf6efc Bump mail container for managesieve fix 2018-05-18 18:26:19 -07:00
Girish Ramakrishnan
07e649a2d3 Add more changes 2018-05-17 20:17:24 -07:00
Girish Ramakrishnan
8c63b6716d Trigger a re-configure 2018-05-17 20:16:51 -07:00
Girish Ramakrishnan
6fd314fe82 Do not change password on app update
Fixes #554
2018-05-17 19:48:57 -07:00
Girish Ramakrishnan
0c7eaf09a9 bump container versions 2018-05-17 10:00:00 -07:00
Girish Ramakrishnan
d0988e2d61 Generate password for mongodb on platform side
Part of #554
2018-05-17 10:00:00 -07:00
Girish Ramakrishnan
4bedbd7167 Generate password for postgresql on platform side
Part of #554
2018-05-17 10:00:00 -07:00
Girish Ramakrishnan
7ca7901a73 Generate password for mysql on platform side
Part of #554
2018-05-17 09:59:57 -07:00
Girish Ramakrishnan
d28dfdbd03 Add 2.3.0 changes 2018-05-17 09:24:47 -07:00
Girish Ramakrishnan
c85ca3c6e2 account setup simply redirects to main page now 2018-05-17 09:17:08 -07:00
Girish Ramakrishnan
da934d26af call callback 2018-05-17 09:16:32 -07:00
Girish Ramakrishnan
f7cc49c5f4 move platform config to db
this way it can be tied up to some REST API later

part of #555
2018-05-16 17:34:56 -07:00
Girish Ramakrishnan
27e263e7fb lint 2018-05-16 14:08:54 -07:00
Girish Ramakrishnan
052050f48b Add a way to persist addon memory configuration
Fixes #555
2018-05-16 14:00:55 -07:00
Girish Ramakrishnan
81e29c7c2b Make the INFRA_VERSION_FILE more readable 2018-05-16 09:54:42 -07:00
Girish Ramakrishnan
c3fbead658 Allow zoneName to be changed in domain update route 2018-05-15 15:39:30 -07:00
Girish Ramakrishnan
36f5b6d678 manual dns: handle ENOTFOUND
Fixes #548
2018-05-15 15:39:18 -07:00
Girish Ramakrishnan
a45b1449de Allow ghost users to skip 2fa 2018-05-14 15:07:01 -07:00
Girish Ramakrishnan
a1020ec6b8 remove /user from profile route 2018-05-13 21:53:06 -07:00
Johannes Zellner
d384284ec8 Add name.com DNS provider in the CHANGES file 2018-05-11 10:03:58 +02:00
Girish Ramakrishnan
bd29447a7f gcdns: Fix typo 2018-05-10 10:05:42 -07:00
Johannes Zellner
aa5952fe0b Wait longer for dns in apptask
name.com often takes longer to sync all nameservers, which means we
timeout too early for them
2018-05-10 15:37:47 +02:00
Johannes Zellner
39dc5da05a We have to return a value on dns record upserting 2018-05-09 18:58:09 +02:00
Johannes Zellner
d0e07d995a Add name.com dns tests 2018-05-09 18:13:21 +02:00
Johannes Zellner
94408c1c3d Add name.com DNS provider 2018-05-09 18:13:14 +02:00
Girish Ramakrishnan
66f032a7ee route53: use credentials instead of dnsConfig 2018-05-07 23:41:03 -07:00
Girish Ramakrishnan
4356df3676 bump timeout 2018-05-07 16:28:11 -07:00
Girish Ramakrishnan
1e730d2fc0 route53: more test fixing 2018-05-07 16:20:03 -07:00
Girish Ramakrishnan
e8875ccd2e godaddy: add tests 2018-05-07 16:09:00 -07:00
Girish Ramakrishnan
2b3656404b route53: fix tests 2018-05-07 15:53:08 -07:00
Girish Ramakrishnan
60b5e6f711 gandi: add tests 2018-05-07 15:51:51 -07:00
Girish Ramakrishnan
b9166b382d route53: set listHostedZonesByName for new/updated domains 2018-05-07 13:42:10 -07:00
Girish Ramakrishnan
d0c427b0df Add more 2.2 changes 2018-05-07 11:46:27 -07:00
Girish Ramakrishnan
da5d0c61b4 godaddy: workaround issue where there is no del record API 2018-05-07 11:41:37 -07:00
Girish Ramakrishnan
1f75c2cc48 route53: add backward compat for pre-2.2 IAM perms
backward compat for 2.2, where we only required access to "listHostedZones"
2018-05-07 11:24:34 -07:00
Girish Ramakrishnan
d0197aab15 Revert "No need to iterate over the hosted zones anymore"
This reverts commit e4a70b95f5.

We will add backward compat route for pre-2.2 cloudrons
2018-05-07 11:23:28 -07:00
Johannes Zellner
e4a70b95f5 No need to iterate over the hosted zones anymore 2018-05-07 16:35:32 +02:00
Johannes Zellner
f4d3d79922 Query only requested Route53 zone
Fixes #550
2018-05-07 16:30:42 +02:00
Girish Ramakrishnan
e3827ee25f Add more 2.2 changes 2018-05-06 23:52:02 -07:00
Girish Ramakrishnan
9981ff2495 Add GoDaddy Domain API 2018-05-06 23:07:52 -07:00
Girish Ramakrishnan
722b14b13d Add note on MX records 2018-05-06 22:14:39 -07:00
Girish Ramakrishnan
eb2fb6491c gandi: more fixes 2018-05-06 21:16:47 -07:00
Girish Ramakrishnan
a53afbce91 Add Gandi LiveDNS backend 2018-05-06 19:48:51 -07:00
Girish Ramakrishnan
31af6c64d0 Expire existing webadmin token so that the UI gets a new token 2018-05-06 13:08:22 -07:00
Girish Ramakrishnan
e8efc5a1b2 Fix test 2018-05-06 12:58:39 -07:00
Girish Ramakrishnan
0c07c6e4d0 Allow "-" in usernames
now that username and mailboxes are totally separate, we can allow '-'.
'+' is still reserved because LDAP it.

Fixes #509
2018-05-05 09:56:21 -07:00
Girish Ramakrishnan
da5fd71aaa Bump mail container for CRAM-MD5 login fix 2018-05-04 21:57:26 -07:00
Girish Ramakrishnan
d57d590363 2.2.0 changes 2018-05-04 10:30:24 -07:00
Johannes Zellner
d6e49415d4 Only list user mailboxes in ldap search 2018-05-04 17:02:04 +02:00
Johannes Zellner
cb73eb61d4 Allow binds against mailboxes 2018-05-04 17:02:04 +02:00
Johannes Zellner
4ce3a262a3 Allow search for mailboxes over ldap for a specific domain 2018-05-04 17:02:04 +02:00
Girish Ramakrishnan
d18d1a977a Add duplicate profile route for compat with old apps using oauth addon 2018-05-03 09:29:46 -07:00
Girish Ramakrishnan
616e38189c Revert "x"
This reverts commit 182ea3dac3.
2018-05-03 09:29:23 -07:00
Johannes Zellner
726cafcee4 Rollback appdb record on clone and install if appstore purchase fails 2018-05-03 13:20:34 +02:00
Girish Ramakrishnan
e5c43e9acd Remove debug 2018-05-02 12:41:22 -07:00
Girish Ramakrishnan
f09e8664d1 Return canonical scope in REST responses
The '*' scope is purely an implementation detail. It cannot
be requested as such.
2018-05-02 12:36:41 -07:00
Girish Ramakrishnan
182ea3dac3 x 2018-05-01 15:17:48 -07:00
Girish Ramakrishnan
97acd40829 remove obsolete roleSdk from the database
the file is renamed because cloudron.io was patched by mistake and we want to run this
migration there
2018-05-01 14:53:46 -07:00
Girish Ramakrishnan
f1abb2149d gravatar url is already generated client side 2018-05-01 14:30:48 -07:00
Girish Ramakrishnan
8c4015851a merge auth.js into accesscontrol.js 2018-05-01 14:03:10 -07:00
Girish Ramakrishnan
a545bdd574 merge developer.js into clients.js 2018-05-01 14:02:59 -07:00
Girish Ramakrishnan
d1135accbd lint 2018-05-01 13:58:13 -07:00
Girish Ramakrishnan
d5b594fade return the scope as part of the user profile
send canonical scope in the profile response
2018-05-01 13:25:47 -07:00
Girish Ramakrishnan
c5ffb65563 Fix usage of normalizeScope 2018-05-01 13:21:53 -07:00
Girish Ramakrishnan
f76a5a7ba7 Move the clients API out of oauth prefix 2018-05-01 11:30:51 -07:00
Girish Ramakrishnan
17bcd95961 typo: return the scope as the scope 2018-05-01 10:59:46 -07:00
Girish Ramakrishnan
23bc0e8db7 Remove SDK Role
Just compare with the token's clientId instead
2018-04-30 23:03:30 -07:00
Girish Ramakrishnan
240ee5f563 Ensure we hand out max user.scope
The token.scope was valid at token creation time. The user's scope
could since have changed (maybe we got kicked out of a group).
2018-04-30 22:51:57 -07:00
Girish Ramakrishnan
200f43a58e lint 2018-04-30 22:41:23 -07:00
Girish Ramakrishnan
61d803f528 Use SCOPE_ANY everywhere 2018-04-30 21:44:24 -07:00
Girish Ramakrishnan
e7c8791356 lint 2018-04-30 21:41:09 -07:00
Girish Ramakrishnan
bc4f9cf596 Remove redundant requireAdmin
We already hand out scopes based on the user's access control
2018-04-30 21:38:48 -07:00
Girish Ramakrishnan
9789966017 Set the scope for a token basedon what the user has access to 2018-04-30 21:21:18 -07:00
Girish Ramakrishnan
1432d90f37 lint 2018-04-30 21:13:23 -07:00
Girish Ramakrishnan
68317a89cb remove the analytics hooks 2018-04-30 15:33:25 -07:00
Girish Ramakrishnan
c84f984205 No need to create a token on password reset 2018-04-30 15:15:05 -07:00
Johannes Zellner
6e19153350 Remove now unused result argument 2018-04-30 20:37:12 +02:00
Johannes Zellner
4dc778f7c2 Change reset password button text 2018-04-30 20:17:56 +02:00
Johannes Zellner
c5c3748aa9 Do not auto login on password reset 2018-04-30 19:55:59 +02:00
Girish Ramakrishnan
f809e359c9 refactor the global variables as functions 2018-04-29 20:17:45 -07:00
Girish Ramakrishnan
91e846d976 Add SCOPE_DOMAINS 2018-04-29 18:11:33 -07:00
Girish Ramakrishnan
b5f8ca6c16 Fix nasssty typo 2018-04-29 17:50:12 -07:00
Girish Ramakrishnan
922ab3bde1 lint 2018-04-29 17:50:12 -07:00
Girish Ramakrishnan
3b7bcc1f61 refactor scopes into accesscontrol.js
this will be our authorization layer for oauth and non-oauth tokens.
2018-04-29 17:50:07 -07:00
Girish Ramakrishnan
6e3b060615 Use SCOPE_PROFILE constant 2018-04-29 17:12:30 -07:00
Girish Ramakrishnan
cc113d0bb5 Add SCOPE_CLIENTS for oauth clients API 2018-04-29 17:03:10 -07:00
Girish Ramakrishnan
3e22d513eb Add SCOPE_MAIL for mail APIs 2018-04-29 17:01:12 -07:00
Girish Ramakrishnan
9cf51ef680 Update cid-webadmin to have all the scopes possible 2018-04-29 16:57:49 -07:00
Girish Ramakrishnan
1c55a3e310 typo 2018-04-29 11:29:21 -07:00
Girish Ramakrishnan
d8acf92929 UserError -> UsersError 2018-04-29 11:22:15 -07:00
Girish Ramakrishnan
7bb8d059b5 GroupError -> GroupsError 2018-04-29 11:21:01 -07:00
Girish Ramakrishnan
863afc68cb DomainError -> DomainsError 2018-04-29 11:20:12 -07:00
Girish Ramakrishnan
4fd58fb46b Rename user.js to users.js 2018-04-29 11:19:04 -07:00
Girish Ramakrishnan
b1b664ceca Move removeInternalAppFields to model code 2018-04-29 10:47:34 -07:00
Girish Ramakrishnan
1a27009fb5 Make expiresAt a body parameter 2018-04-28 22:02:07 -07:00
Girish Ramakrishnan
6c8c206e89 Move input validation logic to routes 2018-04-28 21:58:56 -07:00
Girish Ramakrishnan
82207c3ccd Keep naming consistent with delToken 2018-04-28 21:55:57 -07:00
Girish Ramakrishnan
6768994bbe Capitalize the 2fa text 2018-04-28 10:20:33 -07:00
Girish Ramakrishnan
b72efb1018 Remove private fields when listing domains
Currently, domains list route does not return the fallback cert.
make it future proof, just in case.
2018-04-27 11:41:30 -07:00
Johannes Zellner
7a8c525beb Add 2fa Oauth route tests 2018-04-27 14:08:22 +02:00
Johannes Zellner
9372d8797a Add 2fa tests for developer login api 2018-04-27 12:29:11 +02:00
Johannes Zellner
faeb89b258 Add 2fa token login to oauth login form 2018-04-27 11:46:41 +02:00
Johannes Zellner
50d7ade0d9 Remove unused property on set 2fa secret 2018-04-27 08:20:12 +02:00
Johannes Zellner
497c76a905 Add 2fa token check to developer login 2018-04-27 08:18:13 +02:00
Johannes Zellner
bbc434dc21 Attach the whole user object also for basic authed routes 2018-04-27 08:18:13 +02:00
Girish Ramakrishnan
a7bb5d6b5c add route to query apps specific to user
it's not nice to overload a route to mean different things depending
on who queries it.
2018-04-26 20:07:12 -07:00
Girish Ramakrishnan
e0da6679e9 Move user routes to /api/v1/user 2018-04-26 19:57:44 -07:00
Girish Ramakrishnan
561d2d9f8b admin column is no more in users table 2018-04-26 19:55:26 -07:00
Girish Ramakrishnan
7549b3e837 enhance user creation API to take a password 2018-04-26 14:13:40 -07:00
Girish Ramakrishnan
7756c07bc6 Add better text for the secret 2018-04-26 09:39:35 -07:00
Johannes Zellner
0d58a6bf33 Send 2fa auth status with profile info 2018-04-26 16:29:40 +02:00
Johannes Zellner
fbba636fb3 Handle more 2fa route errors 2018-04-26 16:14:37 +02:00
Johannes Zellner
9cd6333cf7 2fa routest work with the req.user object 2018-04-26 15:12:14 +02:00
Johannes Zellner
eb02c182e5 Avoid linter issue 2018-04-26 14:45:12 +02:00
Johannes Zellner
6574b22cf6 Add 2fa routest and business logic 2018-04-26 08:46:35 +02:00
Girish Ramakrishnan
d1ed2aa2ce remove untested route set_admin 2018-04-25 21:43:21 -07:00
Girish Ramakrishnan
c2a762cb29 Do not reserve mailbox names
Now that user management is split from mailboxes, we don't need to
reserve mailbox names anymore.
2018-04-25 21:14:33 -07:00
Girish Ramakrishnan
34d40edef4 Fix issue where docker needs more recent packages
The following packages have unmet dependencies:
 docker-ce : Depends: libseccomp2 (>= 2.3.0) but 2.2.3-3ubuntu3 is to be installed
E: Unable to correct problems, you have held broken packages.
2018-04-25 13:44:53 -07:00
Johannes Zellner
5ceb14cbca Add required 2fa node modules qrcode and speakeasy 2018-04-25 17:03:16 +02:00
Johannes Zellner
38668937ad Fixup database tests 2018-04-25 17:03:16 +02:00
Johannes Zellner
0167f83d4a Handle 2fa fields in userdb code 2018-04-25 17:03:16 +02:00
Johannes Zellner
9e66adb6d0 Add 2fa db record fields to users table 2018-04-25 17:03:16 +02:00
Girish Ramakrishnan
0a537029bc add mailbox domain to the constraint 2018-04-23 10:14:16 -07:00
Girish Ramakrishnan
c0716e86a7 Remove the "or Email"
The email here can be confused with the Cloudron email which it is not.
The preferred approach is to login via username anyway.
2018-04-22 18:29:10 -07:00
Girish Ramakrishnan
50185adcf4 Add 2.1.1 changes 2018-04-18 12:49:11 -07:00
Johannes Zellner
0c728c6af5 Fix mail rest api tests 2018-04-13 12:54:40 +02:00
Johannes Zellner
34d3d79b12 Improve error message when alias name is already taken 2018-04-13 12:37:27 +02:00
Johannes Zellner
ff856a5978 Rename 'address' catchall property to 'addresses' to better indiciate this being an array 2018-04-13 12:15:15 +02:00
Johannes Zellner
c4dad2f55f Fix address property error response in catchall 2018-04-13 12:15:15 +02:00
Girish Ramakrishnan
734286ba2e Add support for installing private docker images 2018-04-12 11:43:57 -07:00
Girish Ramakrishnan
0f7f8af4b2 Use docker 18.03.0-ce
17.12.0-ce has strange issues like https://github.com/moby/moby/issues/34097
2018-04-11 18:25:19 -07:00
Johannes Zellner
60381d938e Fix search and replace mistake 2018-04-11 15:29:37 +02:00
Johannes Zellner
ddaa52163b Update ssl ciphers according to mozillas recommendation 2018-04-11 15:15:29 +02:00
Johannes Zellner
799c1ba05d Improve on the csp header restriction 2018-04-11 13:00:08 +02:00
Johannes Zellner
838838b90d nginx would drop other headers if add_header is defined in the location section 2018-04-11 12:29:57 +02:00
Girish Ramakrishnan
4554d9f2f8 Add more changes 2018-04-10 15:13:04 -07:00
Johannes Zellner
573d0e993e Add CSP header for dashboard 2018-04-10 17:59:06 +02:00
Johannes Zellner
97313fe1c8 Remove other unused assets from the release tarball 2018-04-10 14:08:13 +02:00
Johannes Zellner
944f743438 Use the node modules defined in the dashboard repo 2018-04-10 13:51:01 +02:00
Johannes Zellner
96a5b0e6ba Remove dashboard related node modules 2018-04-10 13:12:42 +02:00
Girish Ramakrishnan
95f7e50065 bump mail container 2018-04-10 00:00:27 -07:00
Girish Ramakrishnan
d6a8837716 mail: verify with the owner id 2018-04-09 13:17:07 -07:00
Johannes Zellner
cc759e3550 set the mailbox record type for apps 2018-04-09 15:39:36 +02:00
Girish Ramakrishnan
bf0dd935e5 mail: add type field 2018-04-07 21:29:44 -07:00
Girish Ramakrishnan
1d761deec0 Fix test 2018-04-07 18:39:17 -07:00
Girish Ramakrishnan
b6335a327c Rename TYPE_* to OWNER_TYPE_* 2018-04-07 18:33:30 -07:00
Johannes Zellner
55d53ef311 Do not succeed if mailbox name is already taken 2018-04-06 16:55:01 +02:00
Johannes Zellner
878940edae Fix sql syntax 2018-04-06 15:54:55 +02:00
Johannes Zellner
15648a3ab2 fix typo name -> username 2018-04-06 14:53:20 +02:00
Johannes Zellner
2fae98dd5b pass the dashboard version as a revision to the gulp file 2018-04-06 07:47:42 +02:00
Girish Ramakrishnan
9beeb33090 mail: validate list and mailbox names 2018-04-05 17:49:16 -07:00
Girish Ramakrishnan
605dc00422 mail: add members field for lists
we have to track the members of a list in the mail app separately
from groups. this is required because users can now have multiple
mailboxes. and because of that we cannot do a 1-1 mapping of group
members to mailboxes anymore. the ui is changed to select mailboxes
when creating a list.
2018-04-05 16:07:38 -07:00
Girish Ramakrishnan
2c8fa01d6d mail: split the functions to add list and mailbox 2018-04-05 15:01:28 -07:00
Girish Ramakrishnan
467bfa2859 remove mailboxdb from groups code 2018-04-04 20:08:52 -07:00
Girish Ramakrishnan
affb420181 cloudron-setup: highlight reboot in red 2018-04-04 09:55:22 -07:00
Girish Ramakrishnan
e7b26e5655 Add note on accepting self-signed cert 2018-04-04 09:54:14 -07:00
Girish Ramakrishnan
5af657ee22 rename mail crud functions 2018-04-03 15:06:14 -07:00
Girish Ramakrishnan
7fac92c519 validate user id when adding mailbox 2018-04-03 14:27:09 -07:00
Girish Ramakrishnan
f8a731f63a Add routes to change the mailbox and list owner 2018-04-03 14:12:43 -07:00
Girish Ramakrishnan
a1f4a4d614 mail: make mailbox API based on mailbox name
this decouples mail API from users
2018-04-03 13:59:03 -07:00
Girish Ramakrishnan
696e864459 mail: make list API based on list name
this decouples mail API from groups
2018-04-03 12:06:22 -07:00
Girish Ramakrishnan
678ea50f87 validateAlias -> validateName 2018-04-03 09:47:15 -07:00
Girish Ramakrishnan
69d3b3cac8 2.0.2 -> 2.1.0 2018-04-02 13:37:06 -07:00
Girish Ramakrishnan
76915b99a8 Fix linter 2018-04-02 09:46:30 -07:00
Girish Ramakrishnan
255a5a12a5 Decouple mailbox deletion from user delete 2018-04-02 09:45:46 -07:00
Johannes Zellner
602291895c Mention which alias is reserved 2018-04-02 14:59:10 +02:00
Johannes Zellner
045ea4681a Do not return an error on mailinglist listing if none exists
We usually return the empty array, to avoid the need for specific error
handling
2018-04-01 21:51:56 +02:00
Johannes Zellner
e364661813 Send correct status code if mail alias already exists 2018-04-01 19:29:47 +02:00
Johannes Zellner
df9a191434 Add rest api to list all aliases for a given domain 2018-04-01 18:23:54 +02:00
Johannes Zellner
b4aac42032 Add more changes for 2.0.2 2018-04-01 15:15:52 +02:00
Johannes Zellner
2a8be279e7 The package lock now uses sha512 for checksum 2018-04-01 13:15:05 +02:00
Johannes Zellner
4af69fb8c8 Do not show a warning like log, but just dump the tag and detail 2018-03-29 17:36:00 +02:00
Girish Ramakrishnan
cbc98a48ef Slight wording change 2018-03-28 10:17:17 -07:00
Girish Ramakrishnan
874541b988 Add issue templates 2018-03-28 10:14:35 -07:00
Girish Ramakrishnan
0aa1b758ec Update docker to 17.12.0-ce 2018-03-26 16:34:33 -07:00
Girish Ramakrishnan
2e0c632942 Do not crash if mail alias does not validate 2018-03-25 21:08:15 -07:00
Girish Ramakrishnan
82a593e82a Forward stats calls to mail container 2018-03-23 10:52:07 -07:00
Girish Ramakrishnan
e33ebe7304 Revert "mysql: increase max_allowed_packet"
This reverts commit 9123ea7016.

Not needed. This was a db corruption issue
2018-03-22 21:49:08 -07:00
Girish Ramakrishnan
d81930be72 add note on conn limit 2018-03-22 21:07:06 -07:00
Girish Ramakrishnan
aac914182f remove options from database.initialize 2018-03-22 20:34:49 -07:00
Girish Ramakrishnan
26d4a11c44 cleanup eventlog more aggressively
Those login entries are really adding up on old cloudrons
2018-03-22 20:31:32 -07:00
Girish Ramakrishnan
f498443cae remove unused exports 2018-03-22 20:29:26 -07:00
Girish Ramakrishnan
d84d761bad Remove unused export 2018-03-22 19:40:38 -07:00
Girish Ramakrishnan
07601d1292 Fix schema 2018-03-22 18:41:10 -07:00
Girish Ramakrishnan
6cbe964301 Add note 2018-03-22 17:13:32 -07:00
Girish Ramakrishnan
84dcdbba33 Re-assign 2020 to mail server 2018-03-21 23:15:30 -07:00
Girish Ramakrishnan
9123ea7016 mysql: increase max_allowed_packet
some cloudrons are reporting some errors after 2.0. maybe all those
additional joins/fields we put in is causing this
2018-03-21 17:52:22 -07:00
Girish Ramakrishnan
2a18070016 do-spaces: Force retry of 4xx error codes when copying 2018-03-21 15:41:21 -07:00
Girish Ramakrishnan
e0ece06b26 s3: improved copy logging 2018-03-21 14:22:41 -07:00
Girish Ramakrishnan
83d2eb31dd clarify debug 2018-03-21 11:39:16 -07:00
Girish Ramakrishnan
c6b8ad88dd 2.0.2 changes 2018-03-20 20:04:35 -07:00
Girish Ramakrishnan
6adf88a6e5 Make uploads work with very slow upload speeds
chunk uploads get a timeout of 2mins (derived from http.timeout).
On servers like kimsufi, uploads takes forever (100 MB/sec limit).
Currently, our upload code does not dynamically adapt itself to
changing the concurrency when network is slow.
2018-03-20 19:37:45 -07:00
Girish Ramakrishnan
7699f6721d Add hack to figure out the position in the queue
this helps us track the progress a bit in the logs
2018-03-20 19:37:35 -07:00
Girish Ramakrishnan
ce33681c37 Dump etag info 2018-03-20 18:19:14 -07:00
Girish Ramakrishnan
565eed015f Add better backup logs 2018-03-20 16:41:45 -07:00
Girish Ramakrishnan
dd296544be Remove extra prefix 2018-03-15 14:30:10 -07:00
Girish Ramakrishnan
a07c4423c4 Rename webadmin to dashboard
The box nginx config has to be re-generated but this is always
done at box restart time
2018-03-15 14:14:23 -07:00
Girish Ramakrishnan
65f07cb7c0 Add more changes 2018-03-14 09:15:58 -07:00
Girish Ramakrishnan
8d1a6cb06b Add more changes 2018-03-14 09:14:45 -07:00
Girish Ramakrishnan
873ea0fecd Restart mail server after DKIM keys are generated
Haraka won't do change notification on those
2018-03-13 09:53:41 -07:00
Girish Ramakrishnan
ace1f36f9c 2.0.1 changes 2018-03-13 00:36:58 -07:00
Girish Ramakrishnan
4cc9818139 remove error prone short-circuit update
when we do pre-releases, there really is no way for us to update
all the cloudrons. this worked when everything was managed cloudron.
2018-03-13 00:36:03 -07:00
Girish Ramakrishnan
390639bac0 Bump mail container
This fixes delivery of incoming mail from an outbound only domain
2018-03-13 00:20:48 -07:00
Girish Ramakrishnan
830c685ead recreate mail configs when mail domain is added 2018-03-12 21:14:45 -07:00
Girish Ramakrishnan
65b174f950 Domain removal can fail because of mailbox as well 2018-03-12 09:54:16 -07:00
Girish Ramakrishnan
331ed4e6b9 Pass on any appstore purchase error 2018-03-11 12:43:24 -07:00
Girish Ramakrishnan
afef548097 cloudron-setup: make sure --help runs as non-root 2018-03-09 10:37:18 -08:00
Johannes Zellner
60e924d5b8 We do require a domain entry in the mails table always 2018-03-09 14:26:33 +01:00
Johannes Zellner
c0ea91a688 We have to parse the JSON data from the raw db results 2018-03-09 10:27:13 +01:00
Girish Ramakrishnan
ecf1f9255d relay: cloudron-smtp can always be set 2018-03-08 23:23:02 -08:00
Girish Ramakrishnan
1125643a80 Add Haraka 2.8.18 to changelog 2018-03-08 20:12:34 -08:00
Girish Ramakrishnan
61243f6a09 Wait for DNS records call to finish 2018-03-08 20:08:01 -08:00
Girish Ramakrishnan
2e156aa34a simplify the configureWebadmin logic 2018-03-08 18:26:44 -08:00
Girish Ramakrishnan
440629530f remove redundant check for "test" mode 2018-03-08 18:15:09 -08:00
Girish Ramakrishnan
3922824dc6 no reason to keep retrying 2018-03-08 18:00:16 -08:00
Girish Ramakrishnan
6bc5add023 Add a way to re-sync mail DNS records
Also, make restore resync the admin domain record which gets messed
up by the dns setup
2018-03-08 17:59:53 -08:00
Girish Ramakrishnan
f284245e16 dkim keys are needed for the test 2018-03-08 16:10:33 -08:00
Girish Ramakrishnan
ac62ee5a16 better debug 2018-03-08 15:29:18 -08:00
Girish Ramakrishnan
66f251be06 dnsSetup must fail if domain already exists 2018-03-08 15:10:38 -08:00
Girish Ramakrishnan
ab932c4f5c Do not regenerate domain key if domain already exists 2018-03-08 15:01:08 -08:00
Girish Ramakrishnan
074c6fdba3 More renaming to forum 2018-03-08 10:50:18 -08:00
Girish Ramakrishnan
b36f4becbc remove bad changelog 2018-03-08 10:22:46 -08:00
Girish Ramakrishnan
ac69b96f92 clear timeout when getting mail status 2018-03-08 09:32:06 -08:00
Girish Ramakrishnan
6da7a7d2f4 clear the request timeout when adding/updating domain
DO API takes very long to respond at times :/ Currently, there is
no easy way to reset the timeout middleware timeout. We should add
this feature upstream (https://github.com/expressjs/timeout/issues/26)
2018-03-08 09:27:56 -08:00
Girish Ramakrishnan
22c54ced05 email: add MAIL_DOMAINS 2018-03-07 20:39:58 -08:00
Girish Ramakrishnan
c7b1d49de6 cloudron-setup: add some color 2018-03-07 15:51:00 -08:00
Girish Ramakrishnan
b7bf5b180c Display the format as well 2018-03-07 13:59:17 -08:00
Girish Ramakrishnan
12aba46893 use apps.getAll since app.fqdn is otherwise undefined 2018-03-07 13:39:40 -08:00
Johannes Zellner
9d4eee0dfe reword error message, all apps using a domain have to be deleted 2018-03-07 10:45:03 +01:00
Girish Ramakrishnan
d69c8f49e5 Migrate daily update pattern 2018-03-06 21:29:08 -08:00
Girish Ramakrishnan
dd5f41aee8 Fix failing test 2018-03-06 01:35:38 -08:00
Girish Ramakrishnan
0b20b265de Do not crash if domain is not found 2018-03-06 01:30:40 -08:00
Girish Ramakrishnan
ac94d0b5c7 Make apps also auto-update like before by default 2018-03-05 21:33:18 -08:00
Girish Ramakrishnan
c5a70d10d7 Add robotsTxt to appdb.add 2018-03-05 16:14:23 -08:00
Girish Ramakrishnan
b83eb993d8 Add sso and robotsTxt to app backup config.json 2018-03-05 15:03:03 -08:00
Girish Ramakrishnan
6cadaca307 clone: copy enableBackup and robotsTxt 2018-03-05 14:56:24 -08:00
Girish Ramakrishnan
36b91ae7db Add PSBL 2018-03-05 14:26:53 -08:00
Johannes Zellner
3115432309 Fix missed eventlog.getAllPaged() usage 2018-03-05 17:53:18 +01:00
Johannes Zellner
8340f77e20 Fixup the database tests 2018-03-05 17:17:01 +01:00
Johannes Zellner
75932e2805 Collect app information for feedback email 2018-03-05 17:03:54 +01:00
Johannes Zellner
ff6d468604 Support multiple actions for eventlog api 2018-03-05 11:46:06 +01:00
Girish Ramakrishnan
161b2ac6f5 clone: Fix crash where port conflict is not handled 2018-03-02 19:37:15 -08:00
Johannes Zellner
9775ab5e8e make correct use of eventlog for developer/cli login 2018-03-02 19:26:55 +01:00
Johannes Zellner
726202b040 Amend app object where applicable to login event 2018-03-02 19:21:11 +01:00
Johannes Zellner
39d6ec96b7 amend full user object to login action 2018-03-02 19:21:11 +01:00
Johannes Zellner
87fedb71b7 Use shared function to remove private user fields for api 2018-03-02 11:24:27 +01:00
Johannes Zellner
8424e687cb Amend full user object to user action eventlog entries 2018-03-02 11:24:06 +01:00
Johannes Zellner
c0d030c978 Amend full user object to user eventlog action entries 2018-03-02 11:02:32 +01:00
Johannes Zellner
53470e286f Use app model code to get all amended properties 2018-03-02 10:58:05 +01:00
Girish Ramakrishnan
e22c17eabe Fix issue where new package versions are getting skipped 2018-03-01 11:39:10 -08:00
Girish Ramakrishnan
5ac1fccb98 mail: Fix crashes when user has no username yet 2018-02-28 13:31:28 -08:00
Girish Ramakrishnan
0cc58fafd6 Do not crash if user does not have username 2018-02-28 13:18:41 -08:00
Girish Ramakrishnan
98e19e6df5 fix upload errors causing double callback 2018-02-27 19:16:03 -08:00
Girish Ramakrishnan
441e514119 scheduler: give scheduler tasks twice the memory by default 2018-02-27 15:03:09 -08:00
Girish Ramakrishnan
ff4b09a342 Use the container StartedAt instead of lastDate
CronJob.lastDate keeps resetting on every tick. Also, it doesn't
work across box code restarts.
2018-02-27 14:26:40 -08:00
Girish Ramakrishnan
f8c8133148 scheduler: better debugs 2018-02-27 13:54:38 -08:00
Girish Ramakrishnan
938a41e12c scheduler: give cron jobs a grace period of 30 mins to complete 2018-02-27 13:28:42 -08:00
Girish Ramakrishnan
5d231f4fef scheduler: do no start all cronjobs at once 2018-02-27 12:44:11 -08:00
Girish Ramakrishnan
a4e6181edf Fix tests 2018-02-27 11:59:15 -08:00
Girish Ramakrishnan
6685118b03 Use safe.JSON.parse instead
safe.require() caches the credentials which is annoying
2018-02-27 11:24:08 -08:00
Girish Ramakrishnan
4c9919a98b Drop the "your" 2018-02-27 09:22:43 -08:00
Girish Ramakrishnan
470c9971f8 mail exchange does not have trailing dot 2018-02-23 17:26:28 -08:00
Girish Ramakrishnan
b6fb49956f s3: better debug output when copying 2018-02-22 12:41:18 -08:00
Girish Ramakrishnan
0bba985ff1 storage: Add implementation note 2018-02-22 12:30:55 -08:00
Girish Ramakrishnan
3c8c15db01 s3: use a constant backoff since it takes forever to fail otherwise 2018-02-22 12:30:44 -08:00
Girish Ramakrishnan
c8a6294772 lint 2018-02-22 12:24:16 -08:00
Girish Ramakrishnan
cea83889ec s3: Fix issue where it takes forever to timeout if the backend is down 2018-02-22 12:19:23 -08:00
Girish Ramakrishnan
2ecb66afd7 s3: cleanup code 2018-02-22 12:16:01 -08:00
Girish Ramakrishnan
f5d426fd69 debug out the progress message 2018-02-22 11:11:36 -08:00
Girish Ramakrishnan
e6c07fc148 merge the done callback into the main code 2018-02-22 11:06:28 -08:00
Girish Ramakrishnan
1f30a4f3ea Make s3.deleteObjects return error 2018-02-22 11:05:29 -08:00
Girish Ramakrishnan
0bfdaeb2fb rename to chunkSize 2018-02-22 11:01:04 -08:00
Girish Ramakrishnan
e022dbf8a6 Revert "merge the done callback into the main code"
This reverts commit c39bec8cc1.

This was committed with extra stuff by mistake
2018-02-22 10:58:56 -08:00
Girish Ramakrishnan
0e7e672dd2 Update node modules 2018-02-22 10:52:42 -08:00
Girish Ramakrishnan
6075a7a890 typo 2018-02-22 10:34:48 -08:00
Girish Ramakrishnan
28b864c346 sos: Copy in 96M chunks as recommended by exoscale 2018-02-22 10:31:56 -08:00
Girish Ramakrishnan
e9437131ff mail: set domain_selector to be mail_from 2018-02-21 20:46:32 -08:00
Girish Ramakrishnan
c39bec8cc1 merge the done callback into the main code 2018-02-21 20:17:58 -08:00
Girish Ramakrishnan
727a25f491 DO Spaces: multipart copy now works 2018-02-20 14:48:03 -08:00
Johannes Zellner
26bacfcbd6 Allow partial match of eventlog actions 2018-02-20 11:20:17 -08:00
Johannes Zellner
a777e7aeb3 add full app object to app related eventlog actions 2018-02-20 10:34:09 -08:00
Johannes Zellner
676625a3f6 Add more appstore tests 2018-02-18 22:43:11 -08:00
Johannes Zellner
f41603ea94 Add appstore.sendAliveStatus() tests 2018-02-18 21:42:37 -08:00
Johannes Zellner
18ae958e87 Send all domains with provider with the alive post 2018-02-18 21:36:21 -08:00
Johannes Zellner
d68d4295de Remove unused require 2018-02-18 20:16:17 -08:00
Girish Ramakrishnan
0244529b45 Add more changelog 2018-02-18 02:45:46 -08:00
Girish Ramakrishnan
1d044a7392 Bump mail container for multi-domain support 2018-02-18 00:54:41 -08:00
Girish Ramakrishnan
06eab93f0e restart mail container when mail.ini changes 2018-02-18 00:54:11 -08:00
Girish Ramakrishnan
84b7672509 caas can be a provider 2018-02-17 10:28:03 -08:00
Girish Ramakrishnan
c9cd4ed363 Fix changelog version 2018-02-16 16:43:04 -08:00
Girish Ramakrishnan
05c98ccadb Enable auto-updates for major versions
Cloudron is always rolling releases and we never break compat
2018-02-16 16:01:10 -08:00
Johannes Zellner
cb62cdcfa1 Report dependency error for clone if backup or domain was not found 2018-02-16 10:45:06 -08:00
Girish Ramakrishnan
c0fddf5d8a Version 1.11.0 changes 2018-02-11 01:22:26 -08:00
Girish Ramakrishnan
bcf3e71979 Add API to remove mailboxes by domain 2018-02-11 01:18:29 -08:00
Girish Ramakrishnan
baf5cae58a Fix tests 2018-02-11 00:04:41 -08:00
Girish Ramakrishnan
5c1f9d5686 typo 2018-02-11 00:04:28 -08:00
Girish Ramakrishnan
4d89340c7d Handle FK error when deleting mail domain 2018-02-10 22:49:35 -08:00
Girish Ramakrishnan
0b6846787e The mailboxes domain column must reference the mail domain column 2018-02-10 21:31:50 -08:00
Girish Ramakrishnan
79976cd29d add an extra newline in config 2018-02-10 21:29:00 -08:00
Girish Ramakrishnan
574cf1057e mail: ensure mail is disabled when deleting mail domain 2018-02-10 10:38:45 -08:00
Johannes Zellner
1b3450e3a2 update the altDomain migration to also generate certs with SAN 2018-02-10 15:55:22 +01:00
Girish Ramakrishnan
bec032702d Remove SAN check
-checkhost already checks the SAN. It is implementation dependent
as to whether the CN is checked for.
2018-02-09 14:20:03 -08:00
Girish Ramakrishnan
fc79047bbf Generate fallback cert to contain naked domain in SAN 2018-02-09 13:44:29 -08:00
Girish Ramakrishnan
5263ea860d Add cert tests 2018-02-09 11:19:47 -08:00
Johannes Zellner
5140dee81d Generate a fallback cert for domains added during altDomain migration 2018-02-09 13:08:45 +01:00
Johannes Zellner
24d3195660 Add dns setup and activation route tests 2018-02-09 12:43:20 +01:00
Johannes Zellner
721a4c4349 Validate the adminFqdn in dns setup route 2018-02-09 12:43:03 +01:00
Girish Ramakrishnan
83ff295f6d debug: authenticateMailbox 2018-02-08 18:49:27 -08:00
Girish Ramakrishnan
6decc790d6 Follow CNAME records
DNS records can now be a A record or a CNAME record. All we care
about is them resolving to the public IP of the server somehow.

The main reason for this change is that altDomain is migrated into
domains table and the DNS propagation checks have to work after that.
(previously, the 'altDomain' was a signal for a CNAME check which now
cannot be done post-migration).

In the future, we can make this more sophisticated to instead maybe
do a well-known URI query. That way it will work even if there is
some proxy like Cloudflare in the middle.

Fixes #503
2018-02-08 15:43:31 -08:00
Girish Ramakrishnan
459cf8d0cd Add note on unbound at 127.0.0.1 2018-02-08 14:43:49 -08:00
Girish Ramakrishnan
58386b0c54 remove resolveNs 2018-02-08 14:39:35 -08:00
Girish Ramakrishnan
101c1bda25 translate cancelled errors to timeout errors 2018-02-08 14:27:02 -08:00
Girish Ramakrishnan
d31c948d3e Remove type argument from waitForDns
The function is going to be changed to handle only A/CNAME records
2018-02-08 14:24:11 -08:00
Girish Ramakrishnan
0927c8161c Add note on return value of dns.resolve 2018-02-08 14:10:53 -08:00
Girish Ramakrishnan
4d92aea2f3 Fix usage of callback 2018-02-08 14:10:32 -08:00
Girish Ramakrishnan
0ca2451eaa fix tests 2018-02-08 12:09:06 -08:00
Girish Ramakrishnan
3b987f1970 DNS -> Dns 2018-02-08 12:05:29 -08:00
Girish Ramakrishnan
a7b0ba2178 PTR must be resolved by the domain and not IP 2018-02-08 11:56:25 -08:00
Girish Ramakrishnan
744e6b8af0 replace the verizon smtp 2018-02-08 11:48:55 -08:00
Girish Ramakrishnan
8254e795be add missing export 2018-02-08 11:42:45 -08:00
Girish Ramakrishnan
26c95a25b6 Use the native dns resolver
it now supports cancel()

also, fixes #514
2018-02-08 11:37:58 -08:00
Girish Ramakrishnan
209f37312b createReleaseTarball must use the local branch for master branch 2018-02-08 08:58:20 -08:00
Johannes Zellner
5bd218b3b6 Fix intrinsicFqdn removal breakage 2018-02-08 15:23:38 +01:00
Johannes Zellner
d57b772ada We can use js multiline strings 2018-02-08 15:19:00 +01:00
Johannes Zellner
b6384d5025 Remove intrinsicFqdn 2018-02-08 15:07:49 +01:00
Johannes Zellner
fa65576688 Remove unused require 2018-02-08 15:04:13 +01:00
Johannes Zellner
3572b4eb91 Do not crash if certs cannot be found. Error object does not exist 2018-02-08 10:27:30 +01:00
Johannes Zellner
e710a210fd Fixup the unit tests 2018-02-08 09:00:31 +01:00
Johannes Zellner
265db7d0f7 Fix typo in appdb 2018-02-08 09:00:31 +01:00
Johannes Zellner
b1939e73f4 Remove all occurances of altDomain in the code
Tests are pending
2018-02-08 09:00:31 +01:00
Johannes Zellner
28f5f62414 Add altDomain migration script 2018-02-08 09:00:31 +01:00
Girish Ramakrishnan
ff577a8ed5 stop and disable postfix for good measure 2018-02-07 09:08:04 -08:00
Johannes Zellner
63d06d7024 Use fresh settings key for app autoupdate pattern 2018-02-07 16:51:53 +01:00
Johannes Zellner
4d4b77d6fb Add 1.10.2 changes 2018-02-07 16:27:54 +01:00
Johannes Zellner
3b4ff18881 Keep the invite email for users, which have not yet setup a username 2018-02-07 16:27:49 +01:00
Girish Ramakrishnan
d65cb93158 Remove obsolete action 2018-02-06 23:14:02 -08:00
Girish Ramakrishnan
e00f98884c setup SPF record of non-primary domain correctly 2018-02-06 23:11:47 -08:00
Girish Ramakrishnan
21016cc2e0 createReleaseTarball: Make sure we pick the current branch on webadmin 2018-02-06 16:20:29 -08:00
Girish Ramakrishnan
d12803bb9d Add 1.10.1 changes 2018-02-06 16:11:06 -08:00
Girish Ramakrishnan
039a31318a Generate per-domain enable_outbound relay settings 2018-02-06 14:43:14 -08:00
Johannes Zellner
3eb11ee20a Fixup updatechecker tests 2018-02-06 19:25:03 +01:00
Johannes Zellner
11d740682e Split box and app autoupdate pattern settings 2018-02-06 19:25:03 +01:00
Johannes Zellner
09b33e7ef9 Disable autoupdates by default 2018-02-06 19:25:03 +01:00
Johannes Zellner
19fafca9df Drop users email unique constraint for the migration timeframe 2018-02-06 12:14:11 +01:00
Girish Ramakrishnan
da29c69be4 generate per-domain mail configuration 2018-02-05 15:13:35 -08:00
Johannes Zellner
c4531e32d5 Fix all app route tests 2018-02-05 22:17:16 +01:00
Johannes Zellner
8f74cacfd0 Remove unused require 2018-02-05 20:45:53 +01:00
Girish Ramakrishnan
9ba830ab21 "installing" is easier to understand 2018-02-05 11:13:51 -08:00
Girish Ramakrishnan
ad152bacdd Do not allow dns setup and restore to run in parallel
In the e2e, we did not check the webadminStatus after a dnsSetup
and immediately rushed into restore. This ended up mangling the
cert/key files of the admin domain.
2018-02-05 09:35:16 -08:00
Johannes Zellner
89673fa7f0 Make more of the app route tests work 2018-02-05 17:28:30 +01:00
Johannes Zellner
c8613e646b Show more descriptive error message if minBoxVersion blocks update 2018-02-05 15:20:42 +01:00
Girish Ramakrishnan
faef3114f5 Add more 1.10 changes 2018-02-04 09:33:44 -08:00
Girish Ramakrishnan
087f14643a catch_all_address in settings table is JSON 2018-02-04 01:27:40 -08:00
Girish Ramakrishnan
77fe595970 lint 2018-02-04 00:15:41 -08:00
Girish Ramakrishnan
14529d313a sos: CopySource requires fancier encoding rules 2018-02-04 00:12:28 -08:00
Girish Ramakrishnan
72f56ff91c rename the gcdns key file 2018-02-03 22:18:04 -08:00
Girish Ramakrishnan
2a7eabfa68 fix test mail route 2018-02-03 18:34:11 -08:00
Girish Ramakrishnan
d18fe0a40c app: Check altDomain when saving certs 2018-02-03 01:03:23 -08:00
Girish Ramakrishnan
8f5105388f Fix crash when cert renewal fails 2018-02-02 21:21:51 -08:00
Girish Ramakrishnan
4c0da7a8c9 use fallback cert of altDomain 2018-02-02 20:29:04 -08:00
Girish Ramakrishnan
f607010396 sos: remove exoscale specific hacks which are obsolete now 2018-02-02 20:13:51 -08:00
Girish Ramakrishnan
909db5b80e put the ui version in the string as well 2018-02-02 19:57:55 -08:00
Girish Ramakrishnan
7563dd4ac8 remove ununsed require 2018-02-02 18:49:55 -08:00
Girish Ramakrishnan
de1af3ac72 typo 2018-02-02 16:01:20 -08:00
Girish Ramakrishnan
2b9e90397d Do not delete the old conf dir (migration might use it) 2018-02-02 15:44:49 -08:00
Girish Ramakrishnan
8e258f11ec caas: import appstore and caas configs for existing caas 2018-02-02 13:29:57 -08:00
Johannes Zellner
2e818fd689 Make first half of the app route tests pass 2018-02-02 14:06:01 +01:00
Girish Ramakrishnan
f85b7a4336 How many commits to fix a typo? 2018-02-01 22:24:41 -08:00
Girish Ramakrishnan
f4a021b751 Fix path to nginx cert 2018-02-01 21:58:42 -08:00
Johannes Zellner
272b0489ff Fixup the app route test startup sequence 2018-02-01 18:04:43 +01:00
Johannes Zellner
1b25a0d7b7 Fix copy'n'paste error 2018-02-01 17:28:04 +01:00
Johannes Zellner
d8b62f95be Fix domains tests 2018-02-01 11:19:42 +01:00
Johannes Zellner
b337300a7b Do not use removed setTlsConfig in apptask tests 2018-02-01 11:16:55 +01:00
Girish Ramakrishnan
2083b035e8 create images in sfo2 now 2018-01-31 22:36:00 -08:00
Girish Ramakrishnan
2873793e7b typo 2018-01-31 22:31:19 -08:00
Girish Ramakrishnan
17128f0b56 Start the platform code only after 3 secs 2018-01-31 22:16:06 -08:00
Girish Ramakrishnan
1f5ecd5ff8 Set default for CAAS_CONFIG_KEY 2018-01-31 21:48:33 -08:00
Girish Ramakrishnan
52e23c1299 createReleaseTarball: warn about uncommitted changes in webadmin 2018-01-31 20:48:12 -08:00
Girish Ramakrishnan
298a2d2f0f cloudron-setup: remove unused source-url 2018-01-31 20:14:31 -08:00
Girish Ramakrishnan
38b6e49d44 cloudron-setup: remove unused dns-provider 2018-01-31 20:11:13 -08:00
Girish Ramakrishnan
d915ea348f cloudron-setup: tls-provider is obsolete 2018-01-31 20:10:47 -08:00
Girish Ramakrishnan
8014cc8ae1 le -> letsencrypt 2018-01-31 18:53:29 -08:00
Girish Ramakrishnan
7dc7c56e97 Fix tests 2018-01-31 18:23:49 -08:00
Girish Ramakrishnan
a5af87e47a caas: never return key 2018-01-31 18:22:33 -08:00
Girish Ramakrishnan
ab7448926f Fix use of fallback certs
We used to always use nginx cert dir. When custom fallback certs
were set, we used to copy it in boxdata cert dir and then nginx cert dir.

The issue is then that we have to copy all certs to nginx cert dir on
cloudron restore.

To fix this, we simply give priority to nginx cert dir and not copy
around certs anymore. caas cert will reside in nginx cert dir and
not get backed up, as expected.
2018-01-31 18:20:29 -08:00
Johannes Zellner
a727fc5efa Use tlsConfig from domain, not settings in reverseproxy 2018-01-31 18:37:08 +01:00
Johannes Zellner
0b31568c14 Remove tlsConfig from the settings code 2018-01-31 18:27:31 +01:00
Johannes Zellner
9b21167a8d Use tlsConfig from the domain, not from settings 2018-01-31 18:27:18 +01:00
Johannes Zellner
3c198550be Do not send tlsConfig with alive status 2018-01-31 18:27:02 +01:00
Johannes Zellner
31be178210 Add tlsConfig provider validation 2018-01-31 18:20:11 +01:00
Johannes Zellner
d1ef35ae1d Fixup all the tests to use domain tlsConfig 2018-01-31 18:09:38 +01:00
Johannes Zellner
1ec294a04b Add tlsConfig to domains and setup rest apis 2018-01-31 17:42:26 +01:00
Johannes Zellner
75775fa192 Add tlsConfig in domain model code 2018-01-31 16:57:59 +01:00
Johannes Zellner
5db1716664 Add tlsConfig handling in domaindb.js 2018-01-31 16:56:22 +01:00
Johannes Zellner
2db35e42de Add migration script for tlsConfig in domains 2018-01-31 16:53:00 +01:00
Johannes Zellner
5521e17313 Remove progress.json generation in start.sh 2018-01-31 11:56:51 +01:00
Johannes Zellner
35d2755cfb Remove splashpage logic 2018-01-31 09:24:43 +01:00
Johannes Zellner
8ee1c87c45 Do not setup the splashscreen anymore 2018-01-31 09:11:04 +01:00
Johannes Zellner
e1533ccd54 Prefix all installer log output for better tracking 2018-01-31 09:10:51 +01:00
Girish Ramakrishnan
7907dd5c4f migrate any existing host.cert/key to domain based host.cert/key
we don't remove the old one's yet since existing nginx config
might still be referencing them (not sure)
2018-01-30 22:09:55 -08:00
Girish Ramakrishnan
be66d1ff4d arg_fqdn is no more 2018-01-30 21:27:27 -08:00
Girish Ramakrishnan
686a01b3e6 autoprovision: Save tlsKey/tlsCert with domain prefix 2018-01-30 20:41:52 -08:00
Girish Ramakrishnan
3299efc113 typos 2018-01-30 20:38:58 -08:00
Girish Ramakrishnan
7a15777ca5 1.9.4 changes 2018-01-30 19:54:04 -08:00
Girish Ramakrishnan
a553a5de79 Copy over the correct license file 2018-01-30 19:52:03 -08:00
Girish Ramakrishnan
21f11c4136 cloudron-setup: remove many obsolete args 2018-01-30 19:51:58 -08:00
Girish Ramakrishnan
cd31ed23bc rewrite renewAll to use existing functions 2018-01-30 16:34:26 -08:00
Girish Ramakrishnan
639a0eb43b Move the BOX_ENV check for more test coverage 2018-01-30 16:14:05 -08:00
Girish Ramakrishnan
86cf8bf9e7 Add auditSource to ensureCertificate 2018-01-30 15:16:34 -08:00
Girish Ramakrishnan
8e500e0243 caas: make the cert provider use domain fallback certs 2018-01-30 14:18:34 -08:00
Girish Ramakrishnan
781cc3b67a Merge ensureCertificate and configuring nginx 2018-01-30 13:54:13 -08:00
Girish Ramakrishnan
f379724128 merge certificates.js and nginx.js to reverseproxy.js
when certs change, we have to call into nginx anyway. since they
go hand in hand, just merge those files. modern reverse proxies
do this job integrated already.
2018-01-30 12:26:09 -08:00
Girish Ramakrishnan
8e63d63509 Move configureDefaultServer to nginx.js 2018-01-30 12:01:53 -08:00
Girish Ramakrishnan
c84f84b9fe host.cert and host.key are not used anymore 2018-01-30 11:58:26 -08:00
Girish Ramakrishnan
fd913de913 Fallback certs are in host.cert/host.key 2018-01-30 11:43:51 -08:00
Girish Ramakrishnan
3336614702 Make getFallbackCertificate return path like getCertificate 2018-01-30 11:30:35 -08:00
Girish Ramakrishnan
f2372c2c75 Fallback certs are named host.cert and host.key 2018-01-30 11:08:58 -08:00
Girish Ramakrishnan
4a4f1b883a Rename getAdminCerticate to getCertificate 2018-01-30 11:04:13 -08:00
Johannes Zellner
79f2709f3a Ensure certificates and nginx configs on startup 2018-01-30 16:55:13 +01:00
Johannes Zellner
8dea0f71f3 Fix typo with intrinsicFqdn 2018-01-30 16:46:51 +01:00
Johannes Zellner
28cffbb168 fix config-test, fqdn is gone 2018-01-30 14:09:59 +01:00
Johannes Zellner
a662362df7 Add mailinglist rest api tests 2018-01-30 12:23:08 +01:00
Johannes Zellner
f54197afe4 return 204 on mailinglist removal api 2018-01-30 12:22:55 +01:00
Johannes Zellner
2745511e67 Fix typo when using HttpSuccess instead of HttpError 2018-01-30 12:14:08 +01:00
Girish Ramakrishnan
2c60c4eb82 move all setup logic to setup.js 2018-01-29 15:51:36 -08:00
Girish Ramakrishnan
c57c372adf remove config.fqdn() completely 2018-01-29 15:11:43 -08:00
Girish Ramakrishnan
1791617f33 typo 2018-01-29 15:11:43 -08:00
Girish Ramakrishnan
e844e1400e zoneName is gone from config 2018-01-29 15:11:43 -08:00
Girish Ramakrishnan
1f2cfc45b5 adminFqdn is only valid if we have a admin domain set 2018-01-29 15:11:43 -08:00
Johannes Zellner
3c3d44e7f8 Add email alias route tests 2018-01-29 19:39:07 +01:00
Johannes Zellner
6470803604 Do not check if email is enabled when an app tries to do sendmail auth through ldap 2018-01-29 19:29:04 +01:00
Johannes Zellner
edb02c859b Add mailbox rest api tests 2018-01-29 18:53:51 +01:00
Girish Ramakrishnan
351b5fcd70 Use config.adminDomain in tests 2018-01-29 09:28:26 -08:00
Girish Ramakrishnan
4c78a2933f config.setZoneName is gone 2018-01-29 09:06:01 -08:00
Johannes Zellner
9041da62e7 fix email route tests 2018-01-29 17:45:10 +01:00
Johannes Zellner
1e9b37053d Add email domain rest api CRUD testing 2018-01-29 17:18:01 +01:00
Johannes Zellner
6115b1cecf return 409 when an email domain conflict is found 2018-01-29 17:17:47 +01:00
Johannes Zellner
ec7b550ca6 Fixup the ldap tests 2018-01-29 13:35:22 +01:00
Johannes Zellner
66ece2243b Actually return an error if we try to update a non existing email domain 2018-01-29 13:28:11 +01:00
Johannes Zellner
77961e51ec mail.get() returns a MailError 2018-01-29 13:14:08 +01:00
Johannes Zellner
c95de547eb Fix config tests to match the removal of zoneName and repurpose of fqdn 2018-01-29 10:11:09 +01:00
Girish Ramakrishnan
b2363271aa add config.adminDomain 2018-01-28 14:26:41 -08:00
Johannes Zellner
3b2f286ac5 certificates init/uninitialize are gone 2018-01-28 20:59:20 +01:00
Girish Ramakrishnan
9ff1b19c3f Remove unused config.zoneName 2018-01-27 09:26:17 -08:00
Girish Ramakrishnan
64f90abac7 Remove onDomainConfigured 2018-01-26 22:56:15 -08:00
Girish Ramakrishnan
7ce79505ee remove overcomplicated certificate events 2018-01-26 22:47:05 -08:00
Girish Ramakrishnan
b4f945f977 do not regenerate fallback certificate 2018-01-26 22:47:05 -08:00
Girish Ramakrishnan
c2d348fe72 remove unused /api/v1/settings/admin_certificate 2018-01-26 20:49:48 -08:00
Girish Ramakrishnan
44324f4501 make certificates.validateCertificate return CertificatesError 2018-01-26 20:39:58 -08:00
Girish Ramakrishnan
6789e9cfe7 change order of validateCertificate args 2018-01-26 20:36:31 -08:00
Girish Ramakrishnan
4d72dfd3da remove ensureFallbackCertificate 2018-01-26 20:31:48 -08:00
Girish Ramakrishnan
66d90c36fc generate fallback cert for domains if not provided 2018-01-26 20:30:37 -08:00
Girish Ramakrishnan
d0bf315859 certificates: cert/key cannot be null 2018-01-26 20:06:17 -08:00
Girish Ramakrishnan
f49ff2985c certificates: setFallbackCertificate does not validate anymore 2018-01-26 20:03:24 -08:00
Girish Ramakrishnan
ca839ea5cb remove dead comment 2018-01-26 19:55:01 -08:00
Girish Ramakrishnan
ce2d39d54c cloudron-setup: add hetzner in the help text 2018-01-26 18:53:50 -08:00
Johannes Zellner
6ef57d3f23 Fix various route handling tests 2018-01-26 21:31:22 +01:00
Girish Ramakrishnan
de8f7415c3 use config.adminFqdn instead of config.fqdn 2018-01-26 12:12:22 -08:00
Johannes Zellner
7441e11c2d Further test fixes to oauth, ldap and mail tests 2018-01-26 21:10:53 +01:00
Johannes Zellner
c3211c7603 Add domain and enable mail on it for many tests 2018-01-26 20:36:27 +01:00
Johannes Zellner
f028b4a232 Remove mailing list logic from groups tests 2018-01-26 20:07:23 +01:00
Johannes Zellner
004211a683 Remove mailbox and alias related tests in the user logic testing 2018-01-26 20:05:09 +01:00
Johannes Zellner
7d65f341db Ensure user tests have the domain setup correctly and remove implicit mailbox check 2018-01-26 18:47:51 +01:00
Johannes Zellner
7e378b426e Fixup the database tests 2018-01-26 18:32:13 +01:00
Johannes Zellner
3135c227d7 Do not add default domain records when we clear the db for testing 2018-01-26 18:32:01 +01:00
Johannes Zellner
3948cfc33b Parse sql error message to deliver correct conflict errors 2018-01-26 17:56:07 +01:00
Johannes Zellner
ccdf926976 move mailbox cleanup code from userdb to user businesslogic 2018-01-26 12:26:03 +01:00
Johannes Zellner
40f73f6c4b Cleanup the mailboxes for groups on deletion 2018-01-26 11:40:28 +01:00
Johannes Zellner
50e0856803 Do not automatically create mailboxes for groups 2018-01-26 11:36:26 +01:00
Johannes Zellner
d95a670dd7 Add mailing lists routes and logic 2018-01-26 11:25:45 +01:00
Girish Ramakrishnan
16b1b27bfb readDkimPublicKeySync has moved 2018-01-25 15:38:29 -08:00
Girish Ramakrishnan
15fbfd3042 create maildb entry in database._clear 2018-01-25 15:20:53 -08:00
Girish Ramakrishnan
aabd1e7df6 Fix crash when adding a domain 2018-01-25 14:51:07 -08:00
Girish Ramakrishnan
9059a30b89 refactor dns logic in cloudron.js 2018-01-25 14:46:48 -08:00
Girish Ramakrishnan
669b94b0d1 test: remove used of config.fqdn 2018-01-25 14:11:52 -08:00
Girish Ramakrishnan
6cb9779537 mail: Add DNS records when mail domain is created 2018-01-25 14:11:46 -08:00
Girish Ramakrishnan
caf8da331c Do not export configureWebadmin 2018-01-25 13:40:06 -08:00
Girish Ramakrishnan
67eb7a290f Fix mail domain route 2018-01-25 13:40:02 -08:00
Girish Ramakrishnan
af6d8f41ee create dkim key when mail domain is added 2018-01-25 10:38:59 -08:00
Girish Ramakrishnan
7c361a87b0 validate appstore update responses 2018-01-25 09:39:34 -08:00
Johannes Zellner
aab175ea05 Remove alias handling from user logic to mail logic 2018-01-25 18:03:26 +01:00
Johannes Zellner
647582a246 Add alias route handler and logic to mail.js 2018-01-25 18:03:02 +01:00
Johannes Zellner
7bba63d911 rename mailbox routes to match overall scheme of plurals 2018-01-25 12:27:28 +01:00
Girish Ramakrishnan
b71c0bde55 add routes to create and delete mail domain 2018-01-25 12:09:30 +01:00
Girish Ramakrishnan
ef3ab44199 update cloudron-manifestformat (for prerelease in semver) 2018-01-24 20:09:14 -08:00
Girish Ramakrishnan
ed3f128bcd Send relay, catchall and domain info from mail table 2018-01-24 15:38:45 -08:00
Girish Ramakrishnan
2f5ab98284 remove config.zoneName() use 2018-01-24 15:01:54 -08:00
Girish Ramakrishnan
ee66893875 more config.fqdn() removal in tests 2018-01-24 14:58:37 -08:00
Girish Ramakrishnan
45456f2cf7 Remove unused maildb.addDefaultDomain 2018-01-24 14:42:45 -08:00
Girish Ramakrishnan
df3c127584 fqdn -> domain 2018-01-24 14:28:35 -08:00
Girish Ramakrishnan
9d409a67fd Default to domain because tld.getDomain returns null for some tld's 2018-01-24 14:17:26 -08:00
Girish Ramakrishnan
2e05483d54 refactor: addDnsRecords now takes a domain 2018-01-24 14:08:25 -08:00
Girish Ramakrishnan
4e267c7cd1 mail: remove config.fqdn use 2018-01-24 12:28:47 -08:00
Girish Ramakrishnan
efc6a5acd0 Return NOT_FOUND if app is missing in appstore 2018-01-24 10:56:26 -08:00
Johannes Zellner
962ebc835d Do not error if mailbox state is already correct 2018-01-24 15:44:05 +01:00
Johannes Zellner
c7282e861c Add missing MailError type 2018-01-24 15:38:19 +01:00
Johannes Zellner
358048e02b Add domain specific mailbox routes and logic 2018-01-24 13:11:35 +01:00
Johannes Zellner
666f42f4ef Do not automatically create mailboxes for users 2018-01-24 12:56:12 +01:00
Johannes Zellner
aca07765c9 remove unused require 2018-01-24 12:55:44 +01:00
Johannes Zellner
a3caad46a2 Add unique constraint to our schema description file 2018-01-24 10:51:46 +01:00
Girish Ramakrishnan
5e688944e8 dns: compute subdomain correctly when zone name and domain differs 2018-01-23 20:25:45 -08:00
Girish Ramakrishnan
ed75364e2b Default to tld.getDomain if zone name is not provided 2018-01-23 18:54:05 -08:00
Girish Ramakrishnan
d33e35fda2 Move send_test_mail under mail domain api 2018-01-23 16:10:23 -08:00
Girish Ramakrishnan
ccaf687e91 remove config.fqdn from settings-test 2018-01-23 15:47:41 -08:00
Girish Ramakrishnan
ab447120dc cloudflare: del returns 200 now 2018-01-23 14:52:41 -08:00
Girish Ramakrishnan
9e0e99cb0c Use new mail.ini parameters 2018-01-23 14:25:15 -08:00
Girish Ramakrishnan
992a32a8d9 add hetzner as supported provider 2018-01-23 11:37:15 -08:00
Johannes Zellner
4a7b26f940 mail_relay from settings table is also JSON 2018-01-23 16:29:15 +01:00
Johannes Zellner
147c728743 Rename maildb table to mail 2018-01-23 15:45:30 +01:00
Johannes Zellner
ec910e8ca1 Fix hotfix to be able to deal with different webadmin and box code revisions 2018-01-23 12:15:38 +01:00
Johannes Zellner
681813eddd Ensure the mail status check api has consitent toplevel properties 2018-01-23 12:01:00 +01:00
Girish Ramakrishnan
e6f4a9e4a8 Use domain in mail test 2018-01-22 14:49:30 -08:00
Johannes Zellner
27bd0be1fc Remove config.fqdn() from ldap tests 2018-01-22 20:35:21 +01:00
Johannes Zellner
f152dbefad Also check if the domain has mail enabled for ldap sendmail auth 2018-01-22 20:35:08 +01:00
Johannes Zellner
687ba0e248 Verify mailbox against username instead of email 2018-01-22 20:06:18 +01:00
Girish Ramakrishnan
61b5d3e60d createReleaseTarball: Use HEAD instead of --revision 2018-01-22 11:02:21 -08:00
Girish Ramakrishnan
b69d6c42e1 Get webadmin from a level below 2018-01-22 11:02:21 -08:00
Girish Ramakrishnan
924e35294f move ui to separate repo
This separates the platform code from the ui
2018-01-22 11:01:42 -08:00
Johannes Zellner
a6f79854db Further ldap test fixes 2018-01-22 17:53:17 +01:00
Johannes Zellner
591f01bb45 Do not automatically generate the user's email for password verification 2018-01-22 16:12:13 +01:00
Johannes Zellner
8bcd807010 Use main email address for avatar 2018-01-22 16:09:25 +01:00
Johannes Zellner
14dcd71429 Add ui components for fallbackEmail property 2018-01-22 16:06:35 +01:00
Johannes Zellner
9f29438b34 Allow changing fallbackEmail via the profile api 2018-01-22 15:55:55 +01:00
Johannes Zellner
cf94f26d62 Fixup the test using fallbackEmail 2018-01-22 11:52:58 +01:00
Girish Ramakrishnan
6fdb093595 add and remove maildb entries when domain is created and removed 2018-01-21 20:33:21 -08:00
Girish Ramakrishnan
93d5ce63ae fix indent 2018-01-21 15:34:35 -08:00
Johannes Zellner
32152a8b88 Add missing migration file 2018-01-21 14:50:55 +01:00
Johannes Zellner
48d557b242 Replace alternateEmail with fallbackEmail 2018-01-21 14:50:24 +01:00
Johannes Zellner
1e8aa209b1 Add fallbackEmail to user data model 2018-01-21 14:25:39 +01:00
Girish Ramakrishnan
00c1c42b58 Fix mail route tests 2018-01-21 00:59:20 -08:00
Girish Ramakrishnan
f4e1b8874c add maildb entry when domain entry is created 2018-01-21 00:27:28 -08:00
Girish Ramakrishnan
f5b685465f make ldap test use maildb 2018-01-21 00:27:13 -08:00
Girish Ramakrishnan
f49a36f667 Use mail.get() 2018-01-21 00:17:25 -08:00
Girish Ramakrishnan
70fecb8a75 Add mail test 2018-01-21 00:06:08 -08:00
Girish Ramakrishnan
04868f0983 maildb tests 2018-01-20 23:52:16 -08:00
Girish Ramakrishnan
16ac205c7f make mail routes domain based 2018-01-20 23:47:12 -08:00
Girish Ramakrishnan
3ed794e486 Add a single getter for all mail settings 2018-01-20 23:47:12 -08:00
Girish Ramakrishnan
f93963540e Add maildb
also, migrate values from settings table to maildb
2018-01-20 23:47:08 -08:00
Girish Ramakrishnan
777269810f Move mail container creation to mail.js
At this point, mail.js is like an app of it's own
2018-01-20 20:38:35 -08:00
Girish Ramakrishnan
a7de17a160 Move mail related settings to new mail route
there is quite a bit of circular dep between settings, platform and
mail code. this will be removed in future commits.
2018-01-20 20:02:01 -08:00
Girish Ramakrishnan
e724913b6c Move email_status into mail route 2018-01-20 18:37:15 -08:00
Girish Ramakrishnan
b68db9bf05 email -> mail 2018-01-20 18:22:43 -08:00
Girish Ramakrishnan
8da04f6f51 make domaindb.update take object 2018-01-20 10:24:11 -08:00
Girish Ramakrishnan
b64c41758e domaindb.upsert is not used 2018-01-20 10:18:06 -08:00
Girish Ramakrishnan
0eaea12818 make domaindb.add take an object 2018-01-20 10:17:01 -08:00
Girish Ramakrishnan
b098db16cf domaindb: add DOMAINS_FIELDS 2018-01-20 10:05:31 -08:00
Girish Ramakrishnan
dc952f1dd8 remove config.fqdn() from caas-test 2018-01-20 09:50:30 -08:00
Girish Ramakrishnan
ee733d54ea Add mail_domains and mail_default_domain to mail.ini 2018-01-19 23:17:00 -08:00
Girish Ramakrishnan
0e4a0658b2 Remove postman location (unused by dovecot) 2018-01-19 22:10:10 -08:00
Girish Ramakrishnan
20166cd41c make catch_all fully qualified 2018-01-19 20:02:56 -08:00
Girish Ramakrishnan
98d493b2d0 ldap: make mailbox search return fully qualified names 2018-01-19 12:14:43 -08:00
Girish Ramakrishnan
af25485fa0 ldap: Make alias return fully qualified alias 2018-01-19 12:11:33 -08:00
Girish Ramakrishnan
2015e7bce9 ldap: make mailing list search return fully qualified members 2018-01-19 12:11:26 -08:00
Johannes Zellner
2370b12795 Use the db also for crashnotifier to obtain a valid server domain for sending the mail 2018-01-19 19:26:45 +01:00
Johannes Zellner
18a781b956 Collect common mail sending configs in one function 2018-01-19 18:58:34 +01:00
Johannes Zellner
77206a9d3c Remove fqdn usage from all email templates 2018-01-19 18:56:52 +01:00
Girish Ramakrishnan
73800ac6a7 Linter fixes 2018-01-19 09:55:27 -08:00
Girish Ramakrishnan
27dfd1d6c1 Set the dkim selector when generating keys
The box code owns the dkim dir and selector can change per domain
2018-01-18 21:49:45 -08:00
Girish Ramakrishnan
0833f8830c retire script does not require fqdn 2018-01-18 19:44:43 -08:00
Girish Ramakrishnan
28a240a701 send adminFqdn instead of domain in alive route 2018-01-18 19:44:34 -08:00
Girish Ramakrishnan
5be827cd4e remove use of config.fqdn() in ldap test 2018-01-18 19:35:05 -08:00
Girish Ramakrishnan
0f47dcfae6 ldap: mailbox routes now require the cn to be fully qualified 2018-01-18 19:33:38 -08:00
Girish Ramakrishnan
614f13ffd0 move caas tests to separate file 2018-01-18 14:22:07 -08:00
Girish Ramakrishnan
a850c0813b caas: use caas_config for token verification 2018-01-18 13:51:02 -08:00
Girish Ramakrishnan
4b642a407f remove caas dep from tests 2018-01-18 13:50:57 -08:00
Girish Ramakrishnan
6a87558b52 set default provider to generic 2018-01-18 13:41:40 -08:00
Girish Ramakrishnan
606efb8038 remove caas related logic from oauth test 2018-01-18 13:31:08 -08:00
Girish Ramakrishnan
cfa523f3c1 Remove config.fqdn() fallback in apptask 2018-01-18 12:06:20 -08:00
Girish Ramakrishnan
0e7ebc9637 Move SMTPS port to 2465
This curious change is because gogs and gitea have no way to configure
the SMTPS port and rely on port number ending with 465 to determine
SMTPS (!)
2018-01-18 10:38:39 -08:00
Johannes Zellner
94f7b90705 Add 1.9.3 changes 2018-01-18 15:45:17 +01:00
Johannes Zellner
876b4feb49 The DNS provider property moved to the root dns config object 2018-01-18 12:15:44 +01:00
Girish Ramakrishnan
27252fb2cc 1.10.0 changes 2018-01-17 21:10:11 -08:00
Girish Ramakrishnan
6513aebba6 MAIL_IMAP_USERNAME and MAIL_SMTP_USERNAME should be fully qualified
Re-configure the whole infra to propagate the changes
2018-01-17 21:07:53 -08:00
Girish Ramakrishnan
e9be2a7fb7 Remove is_custom_domain use (use adminFqdn instead) 2018-01-17 21:07:13 -08:00
Girish Ramakrishnan
28dac3fdb3 Fix indentation 2018-01-17 21:05:43 -08:00
Girish Ramakrishnan
f4c3ae639e Use app.domain instead of config.fqdn when setting up mail addon 2018-01-17 21:05:22 -08:00
Girish Ramakrishnan
8c8e387012 bump addons 2018-01-17 20:25:57 -08:00
Girish Ramakrishnan
9e8be3fa50 do basic backupId validation 2018-01-17 16:22:50 -08:00
Girish Ramakrishnan
21058f8b61 exchangeBoxTokenWithUserToken is obsolete 2018-01-17 15:59:33 -08:00
Girish Ramakrishnan
cef0cd4b25 config.token() and arg_token are not used anymore 2018-01-17 15:39:32 -08:00
Girish Ramakrishnan
9cd690e8b4 Do not cache box and user config
this is not needed anymore since webadmin does not keep polling this
2018-01-17 15:38:24 -08:00
Girish Ramakrishnan
116befd111 fix test 2018-01-17 15:13:53 -08:00
Girish Ramakrishnan
fe0ff45c37 caas: autoprovision and use caas and appstore configs 2018-01-17 14:11:19 -08:00
Girish Ramakrishnan
337f919451 dnsConfig is unused 2018-01-17 12:25:33 -08:00
Girish Ramakrishnan
03d2e74e1d use constants 2018-01-17 12:25:14 -08:00
Girish Ramakrishnan
2c42653c24 1.9.2 changes 2018-01-17 10:53:00 -08:00
Johannes Zellner
b1109ba6ea Only require the GCS key when this backup provider is selected 2018-01-17 19:38:05 +01:00
Johannes Zellner
7700d236a5 Create new changes for 1.9.1 2018-01-16 22:02:09 +01:00
Johannes Zellner
b10abb1944 Attempt to bring existing logs or terminal window to the front 2018-01-16 19:09:33 +01:00
Johannes Zellner
dd6eeac000 Do not source the xterm assets in the main app 2018-01-16 16:49:34 +01:00
Johannes Zellner
7b8bb5dac4 Add js-terminal task to the default task chain for gulp 2018-01-16 16:49:17 +01:00
Johannes Zellner
bf444a722d Remove debug entry from main menu 2018-01-16 16:32:56 +01:00
Johannes Zellner
a954a23add Add terminal action to apps grid 2018-01-16 16:30:15 +01:00
Johannes Zellner
98aa785ad0 Add showTerminal button to logs view 2018-01-16 16:24:32 +01:00
Johannes Zellner
ee485d8b2a Add separate terminal window 2018-01-16 16:24:18 +01:00
Girish Ramakrishnan
081b596ebf add note that the migration is br0ken 2018-01-15 20:18:32 -08:00
Girish Ramakrishnan
56f4cbe44a Fix double callback invocation in cleanupBackup 2018-01-15 20:08:55 -08:00
Girish Ramakrishnan
ab5b754c22 Add adminFqdn to update params 2018-01-15 13:47:26 -08:00
Johannes Zellner
f030aa95ba Open logs viewer in new window 2018-01-15 16:29:17 +01:00
Johannes Zellner
bad947e2ac Add separate logs viewer 2018-01-15 16:29:03 +01:00
Johannes Zellner
02b43382c8 Remove logs view from the main angular app 2018-01-15 16:28:19 +01:00
Johannes Zellner
4ed35c25a5 Align text size in account and settings view 2018-01-15 14:52:25 +01:00
Johannes Zellner
0d4f963756 Ensure we use the same collation on all tables
This is required since some older cloudrons have a mixed bag of
collations and thus charsets and we add foreign keys across those, which
require the same collation
2018-01-15 11:01:35 +01:00
Girish Ramakrishnan
1139c077b0 Fix usage of domain.provider 2018-01-12 09:25:33 -08:00
Girish Ramakrishnan
84afdb2e3a remove broken links 2018-01-11 15:14:14 -08:00
Girish Ramakrishnan
115f9b408f cloudron-setup: Add adminFqdn 2018-01-11 15:11:49 -08:00
Girish Ramakrishnan
d6ce51dabd Various minor UI fixes 2018-01-11 13:56:51 -08:00
Girish Ramakrishnan
54bc4b32c8 provider cannot be empty string 2018-01-11 11:05:37 -08:00
Girish Ramakrishnan
6537cf700f Fix crash in apps.clone 2018-01-11 10:59:30 -08:00
Johannes Zellner
c5e0b45b22 setupdns view needs to query other domains during migration
The risk for cross site scripting during Cloudron setup is very small
2018-01-11 16:52:39 +01:00
Johannes Zellner
cbfd7cf1a6 Make the new domain available to setupdns view on migration 2018-01-11 16:48:28 +01:00
Johannes Zellner
e96199927d Do not show migrate button for already active domain 2018-01-11 14:57:29 +01:00
Johannes Zellner
a67d690291 Ensure we can migrate caas Cloudrons back to caas domain 2018-01-11 14:33:09 +01:00
Girish Ramakrishnan
30ddda723d typo 2018-01-11 01:00:15 -08:00
Girish Ramakrishnan
d9bf2f1724 If oldConfig.domain is missing use config.fqdn()
do this in configure() because the code asserts on domain being
a string
2018-01-11 00:35:27 -08:00
Girish Ramakrishnan
915cfbe7dd Remove use of isCustomDomain
Use adminFqdn instead as needed
2018-01-11 00:35:12 -08:00
Girish Ramakrishnan
aeb883623b handle location being empty 2018-01-11 00:31:51 -08:00
Girish Ramakrishnan
2d163c1e76 caas: do not special case handling of naked domains
on the caas side, adding naked domain is removed as well
2018-01-11 00:13:16 -08:00
Girish Ramakrishnan
74e79c00fc Fix cert api selection 2018-01-11 00:05:35 -08:00
Girish Ramakrishnan
f87f92708b Fix waitForDNSRecord with external domain 2018-01-10 23:50:59 -08:00
Girish Ramakrishnan
b2ff16eb1e Do not save intrinsicFqdn in db 2018-01-10 23:44:46 -08:00
Girish Ramakrishnan
0c9f557d21 let unregisterSubdomain succeed if domain was removed 2018-01-10 23:17:07 -08:00
Girish Ramakrishnan
f7dd8c0a23 Do not rewrap domain errors 2018-01-10 23:16:46 -08:00
Girish Ramakrishnan
3067e0940d compare with adminFqdn instead of adminLocation 2018-01-10 18:14:29 -08:00
Girish Ramakrishnan
969fba83ea Do not use config.fqdn to determine application name 2018-01-10 15:44:12 -08:00
Girish Ramakrishnan
70a15d01c9 Remove use of isCustomDomain in tokens.html 2018-01-10 14:13:43 -08:00
Girish Ramakrishnan
efc0a3b68d Remove usage of config.appFqdn() 2018-01-10 13:58:05 -08:00
Girish Ramakrishnan
c108cd2d5f Set max email recepient limit (in outgoing emails) to 500 2018-01-10 11:42:41 -08:00
Girish Ramakrishnan
e67f023a56 Remove unused variable 2018-01-09 21:09:10 -08:00
Girish Ramakrishnan
208e4267df Fix validateHostname to handle empty location 2018-01-09 18:17:09 -08:00
Girish Ramakrishnan
92b6464cd7 caas: fix migration of zoneName into domains table 2018-01-09 17:50:04 -08:00
Girish Ramakrishnan
ab66c8cb81 debug the zoneName in waitForDns 2018-01-09 16:09:47 -08:00
Girish Ramakrishnan
2ac12de204 Add domains.provider 2018-01-09 15:32:49 -08:00
Girish Ramakrishnan
373c003223 provider is always set in domain config 2018-01-09 14:25:58 -08:00
Girish Ramakrishnan
f236bd3316 remove isCustomDomain usage from the UI
This also adds domains.provider that we should add to the db itself
at some point
2018-01-09 11:00:32 -08:00
Girish Ramakrishnan
9d386bd071 Fix indent 2018-01-09 10:15:35 -08:00
Girish Ramakrishnan
665aa2ad3d Open the logs in new tab 2018-01-08 17:41:31 -08:00
Girish Ramakrishnan
e8ca423ac4 make setupdns try to get status forever
During domain migration, the box code restarts. the getStatus() will
fail temporarily. In the future, we can make this code forward to
error.html after a few retries.
2018-01-08 17:34:28 -08:00
Girish Ramakrishnan
a53214cb29 Call jquery event handlers in $scope.$apply
This causes all sorts of strange race conditions when $location.path()
is changed by the hide and hidden events handlers
2018-01-08 17:30:50 -08:00
Girish Ramakrishnan
af4296e40c Fix periodic fetching of apps/config/profile
All these are already fetched the first time in main.js

* Fetch apps periodically only in the apps view. This is mostly for the
  installationState. We can optimize this a bit more later depending on
  if any app is in non-running state.

* profile hardly changes, no need to fetch this over and over

* config hardly changes, but is fetched primarily for the update flag
2018-01-08 16:17:02 -08:00
Girish Ramakrishnan
50d396725e Update app state immediately on dialog close 2018-01-08 14:53:28 -08:00
Girish Ramakrishnan
e0c894d333 remove redundant call to fetch user info
main.js already does this
2018-01-08 14:21:25 -08:00
Girish Ramakrishnan
044c25311f add note on why we only use href and not the hostname 2018-01-08 14:21:16 -08:00
Girish Ramakrishnan
d56575facf Add autofocus to error and info dialogs 2018-01-08 14:21:04 -08:00
Girish Ramakrishnan
05775a843d Keep apps sorted 2018-01-08 14:16:07 -08:00
Johannes Zellner
5261831ca2 We have a new year 2018-01-08 12:12:55 +01:00
Johannes Zellner
b0c967ba57 Remove logging parts from terminal/debug view 2018-01-08 11:51:10 +01:00
Johannes Zellner
2902c6ca7a Add logs button in app grid 2018-01-08 11:09:46 +01:00
Johannes Zellner
0c5aea2fb2 Add separate logs view with deep-linking support 2018-01-08 11:05:14 +01:00
Girish Ramakrishnan
de2999cb56 tarjs is not used anymore 2018-01-07 18:34:36 -08:00
Girish Ramakrishnan
28c1a70ae1 Fix display of app install dialog when no version is provided 2018-01-05 11:58:53 -08:00
Girish Ramakrishnan
ff4d3de1b1 redirect to setupdns instead since it will redirect to new domain automatically 2018-01-02 17:34:53 -08:00
Girish Ramakrishnan
ac4f12447b add set admin button 2018-01-02 16:25:30 -08:00
Girish Ramakrishnan
325814e7ca Display the add domain button for caas 2018-01-02 14:52:27 -08:00
Girish Ramakrishnan
00728dc833 caas: move getBoxAndUserDetails 2018-01-02 13:05:30 -08:00
Girish Ramakrishnan
c95684af1e Move caas heartbeat code to caas.js 2018-01-02 12:47:33 -08:00
Girish Ramakrishnan
0a80bff055 Fix indent 2018-01-01 20:09:04 -08:00
Girish Ramakrishnan
9e7b10860d webterminal: Sort entries in dropdown based on location 2017-12-27 07:23:16 -08:00
Girish Ramakrishnan
41eab11641 Add 1.8.5 changes 2017-12-26 07:06:50 -08:00
Girish Ramakrishnan
b7abf404f3 Display external error if appstore download fails 2017-12-26 07:06:08 -08:00
Girish Ramakrishnan
dc644570f7 Use updateConfig addons instead of manifest addons to setup
Even though app.manifest variable is updated by updatedApp, the
setupAddons is called with the _old_ value because it is a bind()
2017-12-21 01:07:40 -08:00
Girish Ramakrishnan
c4cb6b5819 lint 2017-12-21 01:04:38 -08:00
Girish Ramakrishnan
b7e9f0ed12 Add debug for oauth addon setup 2017-12-21 00:50:53 -08:00
Girish Ramakrishnan
46df1d694a gcs: display prefix in restore UI 2017-12-20 09:32:29 -08:00
Girish Ramakrishnan
3efe8e3393 gcs: add to restore UI 2017-12-20 02:06:55 -08:00
Girish Ramakrishnan
e4b12f0c4e gcs: make testfile deletion work
It seems there is a race where the delete gets triggered even before the
file upload is complete. as a result, the delete succeeds but the file
is left on gcs.
2017-12-16 21:36:33 +05:30
Girish Ramakrishnan
61b56d4679 gcs: keyFilename is not used
also, some linter fixes
2017-12-16 21:36:29 +05:30
Girish Ramakrishnan
051ac21fed gcs: make prefix visible 2017-12-15 21:47:54 +05:30
Girish Ramakrishnan
892bd86810 gcs: gcsKey.content is not loaded properly 2017-12-15 21:21:28 +05:30
Girish Ramakrishnan
5c4ae6066d gcs: lint 2017-12-15 17:34:09 +05:30
Girish Ramakrishnan
a35e048665 gcs: oldFilePath is not defined 2017-12-15 17:31:05 +05:30
Girish Ramakrishnan
48f6c39ae5 gcs: Make requires alphabetical 2017-12-15 17:28:45 +05:30
Girish Ramakrishnan
be03bd2c5b shrinkwrap is gone 2017-12-15 17:09:46 +05:30
Girish Ramakrishnan
f108376b25 8.9.3 is required 2017-12-15 17:05:48 +05:30
Girish Ramakrishnan
70e23ed394 Add package-lock.json
https://github.com/npm/npm/pull/16441 has a TLDR
2017-12-15 17:03:37 +05:30
Girish Ramakrishnan
5fbfb7365f Waiting -> Pending 2017-12-15 16:58:38 +05:30
Girish Ramakrishnan
678865fa2a Fix npm warnings
npm WARN The package gulp-sass is included as both a dev and production dependency.
npm WARN The package hock is included as both a dev and production dependency.
npm WARN The package request is included as both a dev and production dependency.
2017-12-15 16:56:54 +05:30
Girish Ramakrishnan
943dc14bf0 Update shrinkwrap for latest node 2017-12-15 16:53:31 +05:30
Girish Ramakrishnan
c3919592ff 1.9.0 changes 2017-12-15 16:49:14 +05:30
Girish Ramakrishnan
442eb8a518 Update node to 8.9.3 LTS 2017-12-15 16:47:11 +05:30
Girish Ramakrishnan
192e4f0a75 gulp-ejs added an options param 2017-12-12 14:07:20 +05:30
Johannes Zellner
921550e3ed Make mocha call process.exit for each run to avoid lingering server instances 2017-12-10 17:49:23 +01:00
Girish Ramakrishnan
7d0cf1a754 caas: migrate -> change_plan 2017-12-09 09:00:10 +05:30
Girish Ramakrishnan
6dec02e1bd caas: refactor migrate and upgrade route 2017-12-09 08:43:59 +05:30
Girish Ramakrishnan
14fc066af7 gcs: Add missing label and keep the listing sorted 2017-12-09 05:40:31 +05:30
Girish Ramakrishnan
8fbad34716 Update shrinkwrap 2017-12-08 06:28:13 +05:30
Girish Ramakrishnan
75a344a316 Merge branch 'feature/gcs' into 'master'
Adding Google Cloud Storage support for Backups

See merge request cloudron/box!18
2017-12-08 00:51:54 +00:00
Girish Ramakrishnan
3b8d500636 1.8.4 changes 2017-12-07 20:20:41 +05:30
Girish Ramakrishnan
a83bce021b Bump mail container for internal email relay fix 2017-12-07 20:20:09 +05:30
Girish Ramakrishnan
725cf297ab Developer scope is obsolete 2017-12-07 04:33:49 +05:30
Aleksandr Bogdanov
5a2de0bcbb Merge remote-tracking branch 'origin/master' into feature/gcs
# Conflicts:
#	webadmin/src/views/certs.js
#	webadmin/src/views/settings.js
2017-12-06 22:47:26 +01:00
Girish Ramakrishnan
cb814a50d7 Fix waitForDNSRecord for subdomain installations 2017-12-06 12:31:25 +05:30
Girish Ramakrishnan
5d34559f0a Fix hostname validation 2017-12-06 07:13:46 +05:30
Girish Ramakrishnan
91ede59241 cloudron-setup: move backupConfig default as migration script
if in autoprovision, then the backupConfig ends up being overwritten
after a restore.
2017-12-05 18:21:25 +05:30
Girish Ramakrishnan
778342906e cloudron-setup: remove dnsConfig
this is not really used since dns setup is the first step now
2017-12-05 18:09:25 +05:30
Girish Ramakrishnan
c42f3341ca cloudron-setup: Add back restore-url and key for pre-1.9 2017-12-05 16:01:16 +05:30
Girish Ramakrishnan
a838b4c521 cloudron-setup: keep pre-1.9 compat for configs 2017-12-05 15:56:47 +05:30
Girish Ramakrishnan
44d4934546 cloudron-setup: create autoprovision.json 2017-12-05 14:55:06 +05:30
Girish Ramakrishnan
49db0d3641 cloudron-setup: remove boxVersionsUrl 2017-12-05 14:53:26 +05:30
Girish Ramakrishnan
2bebed2c19 Add fqdn to caas domain config 2017-12-05 07:16:00 +05:30
Girish Ramakrishnan
2cf2dddcee Fix display of DNS records when not using cloudron-smtp
Fixes #492
2017-12-04 21:24:17 +05:30
Girish Ramakrishnan
306e11ae88 Remove unused requires 2017-12-04 17:10:06 +05:30
Girish Ramakrishnan
568397ec19 caas: send ids in backupDone instead of filenames 2017-11-29 12:39:10 -08:00
Girish Ramakrishnan
459314df17 lock for platform start, so that apps are not installed in between 2017-11-28 23:18:43 -08:00
Girish Ramakrishnan
693bc094cc caas: make fqdn part of dns and s3 credentials 2017-11-28 22:44:40 -08:00
Girish Ramakrishnan
9cdd2df696 set restoring to false 2017-11-28 15:01:59 -08:00
Girish Ramakrishnan
e9b308bb95 Re-purpose the zoneName as the caas domain 2017-11-28 15:00:38 -08:00
Girish Ramakrishnan
432a369bff Add token to dnsConfig 2017-11-28 15:00:38 -08:00
Girish Ramakrishnan
76312495fd Add debug 2017-11-28 15:00:33 -08:00
Girish Ramakrishnan
126d8b9bec stringify and a typo 2017-11-28 02:30:35 -08:00
Girish Ramakrishnan
d001647704 Change path of autoprovision.conf since /root is not readable 2017-11-28 01:23:10 -08:00
Girish Ramakrishnan
8701b36123 make dnsSetup return any provisioning error 2017-11-28 01:20:18 -08:00
Girish Ramakrishnan
c56a24d4fb Autoprovision from autoprovision.json
This is done so that CaaS restore code path can provision correctly
2017-11-27 22:41:32 -08:00
Girish Ramakrishnan
e6eb54d572 More test fixing 2017-11-27 18:19:20 -08:00
Girish Ramakrishnan
68c26c1d12 Fix route/ tests 2017-11-27 16:01:52 -08:00
Girish Ramakrishnan
437312811d wrap seconds 2017-11-27 15:41:37 -08:00
Girish Ramakrishnan
68d4e70823 Add config._reset to tests 2017-11-27 15:27:54 -08:00
Girish Ramakrishnan
74f3a4dd6f remove redundant after() 2017-11-27 14:10:27 -08:00
Girish Ramakrishnan
3a74babcf4 Fix error message 2017-11-27 13:59:56 -08:00
Girish Ramakrishnan
ab2f2c9aab Remove setTimeout from cron.js
this causes scripts to not end since the timeout is not killed
2017-11-27 13:43:25 -08:00
Girish Ramakrishnan
8b11692e37 cron: ensure all jobs are cleaned up 2017-11-27 12:44:04 -08:00
Girish Ramakrishnan
abe04d7d10 ldap: call client.unbind 2017-11-27 12:14:31 -08:00
Girish Ramakrishnan
efe75f0c4e make tests finish
database.uninitialize must be called to drop the connection
2017-11-27 11:57:09 -08:00
Girish Ramakrishnan
b6c20877ea lint 2017-11-27 10:43:12 -08:00
Girish Ramakrishnan
172d5bbdff Remove obsolete setting (now migrated into domains table) 2017-11-24 22:45:32 -08:00
Girish Ramakrishnan
6ed7a91cf9 rename migration timestamps so they appear in correct order
The following migrations are already released in 1.8.3:

20171116203507-apps-rename-newConfigJson-to-updateConfigJson.js
20171116224051-apps-rename-lastBackupId-to-restoreConfigJson.js
2017-11-24 22:39:29 -08:00
Johannes Zellner
61a7f1a126 mailer.start() is gone remove from test 2017-11-25 00:47:00 +01:00
Johannes Zellner
ba49c1e30c Remove accidentally commited debug lines 2017-11-25 00:39:44 +01:00
Girish Ramakrishnan
ca5b69a07d Fix db export/import 2017-11-24 15:31:06 -08:00
Girish Ramakrishnan
998f736e6f Add database.exportToFile 2017-11-24 15:29:56 -08:00
Girish Ramakrishnan
969f8ad11f Add 1.9.0 changes 2017-11-24 14:58:43 -08:00
Johannes Zellner
34ec09588a no need for a special test setup handling in the migration script 2017-11-24 23:48:59 +01:00
Johannes Zellner
4091315589 Make migration down fail if the table cannot be dropped 2017-11-24 23:48:39 +01:00
Johannes Zellner
91fb45584f Add some changes 2017-11-24 23:01:34 +01:00
Girish Ramakrishnan
180a455299 remove mailer.start and stop 2017-11-24 13:58:40 -08:00
Girish Ramakrishnan
a77bf54df7 cron.initialize is required in domain setup for heartbeats 2017-11-24 13:56:34 -08:00
Girish Ramakrishnan
74abce99ac Fix some typos in restore api 2017-11-23 16:37:40 -08:00
Johannes Zellner
b2d27ee26a add 1.8.3 changes 2017-11-24 01:31:15 +01:00
Johannes Zellner
1466104681 Remove obsolete developer mode 2017-11-24 01:31:15 +01:00
Girish Ramakrishnan
4acd0bcdac Remove --restore-url and --restore-key 2017-11-23 13:33:41 -08:00
Girish Ramakrishnan
f9f2bd5c28 Fix crash 2017-11-23 13:17:07 -08:00
Girish Ramakrishnan
a752b7139f Add a break 2017-11-23 12:54:25 -08:00
Girish Ramakrishnan
2becf674ee fix wording 2017-11-23 12:42:46 -08:00
Girish Ramakrishnan
ef2c44ee2f Instead of exact match, only require major+minor to match 2017-11-23 12:36:43 -08:00
Girish Ramakrishnan
a5e5324f97 Add note about restore in setupdns page 2017-11-23 12:19:06 -08:00
Girish Ramakrishnan
479261bcec add restore UI
Add a link from setup page to restore

Part of #439
2017-11-22 23:08:59 -08:00
Girish Ramakrishnan
ac94a0b7f2 Add route to restore box from backup
Part of #439
2017-11-22 23:08:59 -08:00
Girish Ramakrishnan
0f191324fa Add backups.restore to import from box backup
Part of #439
2017-11-22 23:08:59 -08:00
Girish Ramakrishnan
b507ccaa33 Add database.importFileFile
Part of #439
2017-11-22 23:08:59 -08:00
Girish Ramakrishnan
9f6bc0b779 Start platform only on activated 2017-11-22 23:08:28 -08:00
Girish Ramakrishnan
7306f1ddea chown the toplevel mail directory
this helps the restore box logic extract without sudo
2017-11-22 23:08:01 -08:00
Girish Ramakrishnan
dc1d10837b split read/parse of fsmetadata 2017-11-22 23:07:52 -08:00
Girish Ramakrishnan
f58d6c04cc Add DO spaces ams3 2017-11-22 21:03:38 -08:00
Girish Ramakrishnan
f9dda85a38 Fix error code handling 2017-11-22 21:03:34 -08:00
Johannes Zellner
8773c0f6e1 Remove unused requires 2017-11-23 02:36:33 +01:00
Girish Ramakrishnan
72a96c0d6a lint 2017-11-22 12:19:05 -08:00
Girish Ramakrishnan
136ee363a8 Make backups.download take backupConfig 2017-11-22 10:38:04 -08:00
Girish Ramakrishnan
9c5965311f Handle billing required error in clone 2017-11-22 09:05:06 -08:00
Girish Ramakrishnan
78bd819a36 fix indent 2017-11-21 19:18:03 -08:00
Girish Ramakrishnan
48df8b713d add note on enableBackup 2017-11-21 18:09:44 -08:00
Girish Ramakrishnan
0e15fabf88 Do not put app in errored state if backup fails
this will end up sending an email but will put the app itself back
in installed state

Fixes #468
2017-11-21 15:59:25 -08:00
Johannes Zellner
ed83a11248 Hide domain actions 2017-11-21 23:05:07 +01:00
Johannes Zellner
8d69e5f3b9 More test cleanups to support domains api 2017-11-21 02:46:20 +01:00
Girish Ramakrishnan
5dab697fd6 Display backup progress in caas 2017-11-20 14:37:36 -08:00
Johannes Zellner
a94d5d1b3e Add domains REST api tests 2017-11-20 22:53:14 +01:00
Johannes Zellner
9c0af8b13e Fixing sysadmin, settings and clients tests 2017-11-20 20:01:50 +01:00
Johannes Zellner
a08ff89b78 Fix ldap and dns tests 2017-11-20 20:01:50 +01:00
Johannes Zellner
2e06724927 Add mailboxes unique name/domain constraint 2017-11-20 20:01:50 +01:00
Johannes Zellner
f7c7a36fc1 We reuse appFqdn() here for the webadmin 2017-11-20 20:01:50 +01:00
Johannes Zellner
748d1b8471 webadmin: Hide domain actions for caas managed domains 2017-11-20 20:01:50 +01:00
Johannes Zellner
032200b20f cloudron addDnsRecords needs to provide subdomain and domain separately 2017-11-20 20:01:50 +01:00
Johannes Zellner
4cbb751d82 Fix usage of appFqdn in caas dns backend 2017-11-20 20:01:50 +01:00
Johannes Zellner
27e4f0cb82 make *DNSRecords apis take the explicit domain 2017-11-20 20:01:50 +01:00
Johannes Zellner
321bfc6130 Create initial domain record in start.sh if fqdn was provided 2017-11-20 20:01:50 +01:00
Johannes Zellner
635426c37e Drop mailboxes primary key in favor of name+domain constraint 2017-11-20 20:01:50 +01:00
Johannes Zellner
33e7c8e904 Create the admin group only on owner creation
For new cloudrons this will first remove the previously added group and
mailbox entry from the db migration scripts and readds it once we have a
domain on owner creation
2017-11-20 20:01:50 +01:00
Johannes Zellner
616b4b86d8 Reword the dns setup page to indicate more domains can be added later 2017-11-20 20:01:50 +01:00
Johannes Zellner
e3e6fd2bc9 For new cloudrons, the migration scripts cannot rely on an existing
domain
2017-11-20 20:01:50 +01:00
Johannes Zellner
07626dacb5 Ensure certificates needs to be multidomain aware 2017-11-20 20:01:50 +01:00
Johannes Zellner
bf711c6ebb allow to set domain specific fallback certs 2017-11-20 20:01:50 +01:00
Johannes Zellner
a4a3e19a92 Remove configJson field for domain records in postprocess 2017-11-20 20:01:50 +01:00
Johannes Zellner
16db4ac901 Make app configure domain aware 2017-11-20 20:01:50 +01:00
Johannes Zellner
78d6b6d632 Put app configure dialog helper in the correct scope 2017-11-20 20:01:50 +01:00
Johannes Zellner
009b8abf1b dns api now takes full fqdn instead of subdomain 2017-11-20 20:01:50 +01:00
Johannes Zellner
4edd874695 webadmin: add client.getDomain() 2017-11-20 20:01:50 +01:00
Johannes Zellner
dda403caa9 Only show domains in apps view if there are more than one 2017-11-20 20:01:50 +01:00
Johannes Zellner
de44796b6f Handle errors if domain is still used on deletion attempt 2017-11-20 20:01:50 +01:00
Johannes Zellner
53e3626e51 More test fixes for config database and settings 2017-11-20 20:01:50 +01:00
Johannes Zellner
9aa4fdc829 Fixup the dns provider tests 2017-11-20 20:01:50 +01:00
Johannes Zellner
1ccc3b84b8 Fixup various tests for multidomain 2017-11-20 20:01:50 +01:00
Johannes Zellner
d4b6768464 Fixup validateHostname and related tests 2017-11-20 20:01:50 +01:00
Johannes Zellner
6e07a4ec08 Fixup database tests 2017-11-20 20:01:50 +01:00
Johannes Zellner
1cee0f3831 Fix unregisterSubdomain to work during migration from single to multidomain
oldConfig.domain was previously not there and thus might be missing
still
2017-11-20 20:01:50 +01:00
Johannes Zellner
a52747cde0 Avoid logging 'undefined' on success, this looks like a bug otherwise 2017-11-20 20:01:50 +01:00
Johannes Zellner
14d575f514 Make mailboxdb aware of domain field 2017-11-20 20:01:50 +01:00
Johannes Zellner
e43e904622 Refactor all app.location usages to config.appFqdn(app) 2017-11-20 20:01:50 +01:00
Johannes Zellner
1dfa689d1c Make apptask subdomain cleanup multidomain aware 2017-11-20 19:59:40 +01:00
Johannes Zellner
293e401852 Store domain alongside with location in apps oldConfig 2017-11-20 19:59:40 +01:00
Johannes Zellner
c565d0789e webadmin: Show domain where the app is installed 2017-11-20 19:59:40 +01:00
Johannes Zellner
59ae1ac012 Move fallback certificate api to domains 2017-11-20 19:59:40 +01:00
Johannes Zellner
4cf2978088 Remove dns related settings api
This is replaced with the multi domain aware api
2017-11-20 19:59:40 +01:00
Johannes Zellner
707d34cb89 Make app install dialog multi domain aware 2017-11-20 19:59:40 +01:00
Johannes Zellner
20a37030b6 The domain update route returns 204 not 202 2017-11-20 19:59:40 +01:00
Johannes Zellner
e1be8b669f Do not rely on admin subdomain for dns backend config validation 2017-11-20 19:59:40 +01:00
Johannes Zellner
c723b289dc Only validate the nameservers for manual dns backend 2017-11-20 19:59:40 +01:00
Johannes Zellner
7c51c380ae webadmin: Refactor the domains view 2017-11-20 19:59:40 +01:00
Johannes Zellner
d75959772c Add more error handling for domains update route 2017-11-20 19:59:40 +01:00
Johannes Zellner
37e23c9465 Add zoneName support to domains rest API 2017-11-20 19:59:40 +01:00
Johannes Zellner
21c8f63dc1 weadmin: Add domain REST api wrapper 2017-11-20 19:59:40 +01:00
Johannes Zellner
ca3b6e542a Require password for domain deletion route 2017-11-20 19:59:40 +01:00
Johannes Zellner
3e4466a41e Fix appdb.add sql query 2017-11-20 19:59:40 +01:00
Johannes Zellner
c1b5f56ac6 Send domain with app install request 2017-11-20 19:59:40 +01:00
Johannes Zellner
28c3ef772e Ensure we pass full fqdn to domains api from apptask 2017-11-20 19:59:40 +01:00
Johannes Zellner
f1b23005c9 Fix appFqdn() usage to match new api 2017-11-20 19:59:40 +01:00
Johannes Zellner
143ba831f4 Make appFqdn() multidomain aware 2017-11-20 19:59:40 +01:00
Johannes Zellner
5ca31f2484 Send domain as part of the apps routes 2017-11-20 19:59:40 +01:00
Johannes Zellner
5c272fe5d9 Make appdb domain aware 2017-11-20 19:59:40 +01:00
Johannes Zellner
155877534f Fixup apps.validateHostname() 2017-11-20 19:59:26 +01:00
Johannes Zellner
a2a1d842fa Add db migration scripts
This adds domains table and adjusts the apps and mailboxes table accordingly

Also ensure we explicitly set the table collation, this is required
for the foreign key from apps table (utf8) and the newly created
domains table, which by default now would be utf8mb4

Put db table constraint for mailboxes.domain

Update the schema file
2017-11-20 19:59:26 +01:00
Johannes Zellner
260ac0afb7 Remove subdomains.js in favor of multidomain capable domains.js 2017-11-20 19:59:26 +01:00
Johannes Zellner
fb9372d93e Remove unused dns config change event 2017-11-20 19:59:26 +01:00
Johannes Zellner
eb65f9e758 Remove default settings key for DNS_CONFIG 2017-11-20 19:59:26 +01:00
Johannes Zellner
3265d7151c Migrate dns test to domains.js 2017-11-20 19:59:26 +01:00
Johannes Zellner
597af2e034 Do not send obsolete settings.dnsConfig with alive status 2017-11-20 19:59:26 +01:00
Johannes Zellner
0b8f0bf731 Remove subdomains usage in cloudron.js 2017-11-20 19:59:26 +01:00
Johannes Zellner
a7e10cead0 Use domains api in platform 2017-11-20 19:59:26 +01:00
Johannes Zellner
0e74a6df35 Deprecate dns settings api and add dns data migration 2017-11-20 19:59:26 +01:00
Johannes Zellner
3fbaa385c4 Add DNS record specific functions to domains.js 2017-11-20 19:59:26 +01:00
Johannes Zellner
29637bb4f4 Add basic domain setting validation 2017-11-20 19:59:26 +01:00
Johannes Zellner
9dba816711 Add domain routes 2017-11-20 19:59:26 +01:00
Johannes Zellner
9155f49d4c Add domaindb logic 2017-11-20 19:59:26 +01:00
Johannes Zellner
0e62780f55 Add domains table 2017-11-20 19:59:26 +01:00
Girish Ramakrishnan
998bc36673 remove manifest arg to backupApp 2017-11-19 17:58:04 -08:00
Girish Ramakrishnan
c2dbc40473 Move version to the top 2017-11-19 16:36:00 -08:00
Girish Ramakrishnan
cd5a14ce47 Use date object instead of string 2017-11-19 16:11:51 -08:00
Girish Ramakrishnan
917122c812 display last updated in app info 2017-11-19 13:20:20 -08:00
Girish Ramakrishnan
21b8b8deba Fix many links in the readme 2017-11-19 12:16:04 -08:00
Girish Ramakrishnan
44c2aedb57 1.8.2 changes 2017-11-18 02:19:17 -08:00
Girish Ramakrishnan
7e6a83df84 Fix migration callback 2017-11-18 02:11:00 -08:00
Girish Ramakrishnan
ec4910a45e Fix restore 2017-11-17 22:35:56 -08:00
Girish Ramakrishnan
6558c78094 change the json blobs to text 2017-11-17 15:52:40 -08:00
Girish Ramakrishnan
5df92d1903 remove dead code 2017-11-17 15:18:06 -08:00
Girish Ramakrishnan
05affa7d26 remove dead code 2017-11-17 15:17:50 -08:00
Girish Ramakrishnan
46c6c5a5a8 remove double .js 2017-11-17 14:50:53 -08:00
Girish Ramakrishnan
75da751c72 1.8.1 changes 2017-11-17 14:50:53 -08:00
Johannes Zellner
b84f60671e Also fix the restoreConfigJson migration down script 2017-11-17 23:45:22 +01:00
Johannes Zellner
8dcb06cb02 Fix db migration down step for newConfigJson change 2017-11-17 23:41:22 +01:00
Girish Ramakrishnan
83bf739081 Update the license 2017-11-17 10:46:12 -08:00
Girish Ramakrishnan
48a52fae2e LE agreement URL has changed 2017-11-17 10:35:58 -08:00
Girish Ramakrishnan
0ddbda6068 Fix crash 2017-11-16 15:11:12 -08:00
Girish Ramakrishnan
360fa058ea store format information for restoring
fixes #483
2017-11-16 15:01:27 -08:00
Johannes Zellner
489d2022e6 Do not underline errored links 2017-11-16 23:18:50 +01:00
Girish Ramakrishnan
f762d0c0a1 newConfig -> updateConfig 2017-11-16 12:36:07 -08:00
Girish Ramakrishnan
98cad0678d Handle json parse errors with new body-parser module 2017-11-16 11:47:17 -08:00
Girish Ramakrishnan
92acb2954f Rename restoreConfig to manifest in backup table
Only the manifest needs to be preserved in the backup table
2017-11-16 11:25:40 -08:00
Girish Ramakrishnan
00a6e4c982 Show doc url in info dialog
Fixes #486
2017-11-16 10:05:49 -08:00
Girish Ramakrishnan
bf9eb4bd87 Switch the default to logs to show some useful information 2017-11-16 10:05:49 -08:00
Girish Ramakrishnan
2f4940acbd update modules 2017-11-16 09:34:00 -08:00
Girish Ramakrishnan
9f7ca552a6 handle various appstore errors 2017-11-16 00:23:34 -08:00
Girish Ramakrishnan
4272d5be8a Send feedback via API
Fixes #484
2017-11-15 23:31:13 -08:00
Girish Ramakrishnan
1babfb6e87 Allow admins to access all apps
Fixes #420
2017-11-15 19:24:11 -08:00
Girish Ramakrishnan
5663cf45f8 remove redundant reset 2017-11-15 19:08:38 -08:00
Girish Ramakrishnan
d8cb2d1d25 test: reset is already part of setup 2017-11-15 18:56:27 -08:00
Girish Ramakrishnan
174a60bb07 fix linter warnings 2017-11-15 18:56:27 -08:00
Girish Ramakrishnan
3d7094bf28 Handle error in uploadFile 2017-11-15 18:45:23 -08:00
Girish Ramakrishnan
4d6616930a Fix failing test 2017-11-15 18:41:37 -08:00
Girish Ramakrishnan
24875ba292 Handle all errors and set focus correctly
Fixes #485
2017-11-14 18:26:42 -08:00
Johannes Zellner
c58b2677b6 Fixup config tests and do not allow saving random values to the config file
Those will eventually be overwritten by start.sh anyways, we cannot rely
on those
2017-11-15 02:41:40 +01:00
Johannes Zellner
25146e1134 Allow tests to work without a cloudron.conf on disk 2017-11-15 02:40:50 +01:00
Johannes Zellner
c0c35964fe Fix backups tests 2017-11-15 02:29:58 +01:00
Johannes Zellner
0bf9ab0a2b No need to put static database config in cloudron.conf 2017-11-15 02:29:36 +01:00
Johannes Zellner
6d86f4cbda Ensure we only save relevant config values 2017-11-15 02:29:07 +01:00
Girish Ramakrishnan
d2741bbeb9 Allow mailTo to be configurable
Part of #485
2017-11-14 16:24:34 -08:00
Girish Ramakrishnan
690d02a353 Always show the DNS records in the UI 2017-11-14 15:13:56 -08:00
Johannes Zellner
c629db9597 Remove preinstall app bundle support 2017-11-14 23:09:17 +01:00
Aleksandr Bogdanov
994f771d4d Merge remote-tracking branch 'origin/master' into feature/gcs 2017-11-14 20:16:12 +01:00
Girish Ramakrishnan
67fcf85abb Allow restore if already restoring 2017-11-13 18:43:36 -08:00
Girish Ramakrishnan
527eace8f8 Fix j2xml usage 2017-11-13 11:10:42 -08:00
Girish Ramakrishnan
e65230b833 update many dev modules 2017-11-13 10:57:36 -08:00
Girish Ramakrishnan
3e8334040b Update many node modules
also, use rimraf instead of del
2017-11-13 10:57:32 -08:00
Girish Ramakrishnan
2bcd3a8e4d Add a hack to stretch the multi-select box a bit 2017-11-12 02:50:28 -08:00
Girish Ramakrishnan
e75b85fc3a Bump postgresql container to workaround shm issues
reconfiguring the postgresql configuring seems to fix some shm
issues on docker upgrade
2017-11-11 20:52:34 -08:00
Girish Ramakrishnan
c4362d3339 Fix failing ldap test 2017-11-11 17:33:27 -08:00
Girish Ramakrishnan
85e492a632 Fix detection of container id from IP
https://docs.docker.com/engine/api/v1.32/#tag/Network

"Note that it uses a different, smaller representation of a network
than inspecting a single network. For example, the list of containers
attached to the network is not propagated in API versions 1.28 and up."

Verified using:

curl --unix-socket /var/run/docker.sock http::/networks/cloudron
2017-11-11 16:55:43 -08:00
Girish Ramakrishnan
b8d4b67043 update aws-sdk and dockerode 2017-11-11 16:38:40 -08:00
Girish Ramakrishnan
ffacd31259 bump the node version 2017-11-11 16:25:42 -08:00
Johannes Zellner
19f6da88da Do not disable access control elements if no group was created
There are still users to be selected
2017-11-12 00:09:05 +01:00
Girish Ramakrishnan
c0faae4e27 Add more changes for 1.8.0 2017-11-11 11:14:42 -08:00
Girish Ramakrishnan
a19c566eea Always show info box that displays app version
Fixes #478
2017-11-11 11:09:59 -08:00
Girish Ramakrishnan
3ec806452c Update node to 6.11.5 2017-11-10 19:25:08 -08:00
Girish Ramakrishnan
0c73cd5219 Update docker to 17.09 2017-11-10 18:49:28 -08:00
Girish Ramakrishnan
9b6bf719ff 1.7.8 changes 2017-11-09 09:40:26 -08:00
Girish Ramakrishnan
25431d3cc4 Fix the spacing 2017-11-09 09:29:42 -08:00
Girish Ramakrishnan
e0805df3b1 Only show backup warning if using default location 2017-11-09 09:09:39 -08:00
Girish Ramakrishnan
8392fec570 Remove the bold 2017-11-08 20:57:40 -08:00
Girish Ramakrishnan
1c173ca83f Add UI to select users for access restriction 2017-11-08 20:54:38 -08:00
Girish Ramakrishnan
05a67db761 backup must be stored in ext4
Other file systems like FAT/CIFS can error with cryptic error messages
when saving filenames with special characters such as ':'
2017-11-08 12:26:25 -08:00
Girish Ramakrishnan
bb24d5cf9e Order eventlog entries by time 2017-11-08 09:14:55 -08:00
Girish Ramakrishnan
8d2fbe931f Bump max limit to two times ram
part of #466
2017-11-07 10:07:05 -08:00
Girish Ramakrishnan
0a8adaac9f filter out empty usernames from groups
Fixes #472
2017-11-06 11:09:40 -08:00
Girish Ramakrishnan
fa6d151325 Fix update mail templates 2017-11-02 21:34:03 -07:00
Girish Ramakrishnan
a7296a0339 Rename filename to backupId in backup eventlog 2017-11-02 18:17:08 -07:00
Girish Ramakrishnan
a6aee53ec2 Filter out failed backups 2017-11-02 18:13:51 -07:00
Girish Ramakrishnan
963ab2e791 More 1.7.7 changes 2017-11-02 16:30:13 -07:00
Girish Ramakrishnan
ca724b8b03 Add cert renewal and user add/remove in weekly digest 2017-11-02 16:30:10 -07:00
Girish Ramakrishnan
88a929c85e Instead of appstore account, include owner alternate email 2017-11-02 15:10:05 -07:00
Girish Ramakrishnan
2bc0270880 1.7.7 changes 2017-11-02 12:18:51 -07:00
Girish Ramakrishnan
014b77b7aa Fix LE cert renewal failures
LE contacts the server by hostname and not by IP. This means that
when installing and reconfiguring the app it hits the default_server
route since nginx configs for the app are not generated at.

When doing in the daily cert renew, the nginx configs exist and we
are unable to renew the certs.
2017-11-02 11:43:43 -07:00
Girish Ramakrishnan
06f8aa8f29 Remove dead code
getNonApprovedCode code flow is ununsed (and broken by design on
the appstore side).
2017-11-02 10:36:30 -07:00
Girish Ramakrishnan
a8c64bf9f7 Clarify heartbeat code
heartbeats are not sent for self-hosted cloudrons (only managed ones)
2017-11-02 10:26:21 -07:00
Girish Ramakrishnan
41ef16fbec link to memory limit docs 2017-11-01 09:25:05 -07:00
Girish Ramakrishnan
2a848a481b Add newline 2017-11-01 09:25:05 -07:00
Johannes Zellner
3963d76a80 The update dialog does not contain a form anymore
Fixes #467
2017-11-01 11:55:06 +01:00
Girish Ramakrishnan
8ede37a43d Make the dkim selector dynamic
it has to change with the adminLocation so that multiple cloudrons
can send out emails at the same time.
2017-10-31 12:18:40 -07:00
Girish Ramakrishnan
36534f6bb2 Fix indent 2017-10-31 12:12:02 -07:00
Girish Ramakrishnan
7eddcaf708 Allow setting app memory till memory limit
Fixes #466
2017-10-31 12:12:02 -07:00
Aleksandr Bogdanov
2cad93dfd2 Fixing UI to not require credentials be set (GCP use-case has no credentials field) 2017-10-31 12:33:15 +01:00
Aleksandr Bogdanov
9b1f8febf1 Fixing listDir to support batchSize = -1 for non-chunked listings. Also strings extrapolation fix (ES6) 2017-10-31 11:40:00 +01:00
Girish Ramakrishnan
d8d2572aa1 Keep restarting mysql until it succeeds
MySQL restarts randomly fail on our CI systems. This is easily
reproducible:

root@smartserver:~# cp /tmp/mysql.cnf . && systemctl restart mysql && echo "Yes"
Yes
root@smartserver:~# cp /tmp/mysql.cnf . && systemctl restart mysql && echo "Yes"
Yes
root@smartserver:~# cp /tmp/mysql.cnf . && systemctl restart mysql && echo "Yes"
Job for mysql.service failed. See "systemctl status mysql.service" and "journalctl -xe" for details.

There also seems some apparmor issue:
[ 7389.111704] audit: type=1400 audit(1509404778.110:829): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/sys/devices/system/node/" pid=15618 comm="mysqld" requested_mask="r" denied_mask="r" fsuid=112 ouid=0

The apparmor issue is reported in https://bugs.launchpad.net/ubuntu/+source/mysql-5.7/+bug/1610765,
https://bugs.launchpad.net/ubuntu/+source/mysql-5.7/+bug/1658233 and
https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1658239
2017-10-30 16:14:20 -07:00
Girish Ramakrishnan
96a98a74ac Move the mysql block
The e2e is failing sporadically with:

==> Changing ownership
==> Adding automated configs
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

Maybe the dhparam creation is doing something causing mysql to not respond.
2017-10-30 08:03:47 -07:00
Girish Ramakrishnan
d0a244e392 stash adminLocation also 2017-10-29 19:09:03 -07:00
Girish Ramakrishnan
f09c89e33f Remove confusing batchSize logic from listDir
This also fixes a bug in removeDir in DO spaces

thanks to @syn for reporting
2017-10-29 19:04:10 -07:00
Johannes Zellner
d53f0679e5 Also stash the zoneName to settings 2017-10-29 22:40:15 +01:00
Girish Ramakrishnan
527093ebcb Stash the fqdn in the db for the next multi-domain release 2017-10-29 12:08:27 -07:00
Girish Ramakrishnan
bd5835b866 send adminFqdn as well 2017-10-29 09:36:51 -07:00
Aleksandr Bogdanov
51ca1c7384 Refactoring gcs to match the new storage interface 2017-10-29 11:10:50 +01:00
Girish Ramakrishnan
6dd70c0ef2 acme challenges must be answered by default_server
The challenge must be answered even before app nginx config
is available.
2017-10-28 23:39:03 -07:00
Girish Ramakrishnan
acc90e16d7 1.7.6 changes 2017-10-28 21:07:44 -07:00
Girish Ramakrishnan
4b3aca7413 Bump mail container for sogo disconnect fix 2017-10-28 20:58:26 -07:00
Johannes Zellner
8daee764d2 Only require gcdns form input to be valid if that provider is selected 2017-10-28 22:37:56 +02:00
Aleksandr Bogdanov
8d14832c6a Making gcdns credentials field optional in webadmin 2017-10-28 15:14:23 +02:00
Aleksandr Bogdanov
051d04890b Adding Google Cloud Storage support 2017-10-28 15:14:23 +02:00
Girish Ramakrishnan
3dedda32d4 Configure http server to only listen on known vhosts/IP
For the rest it returns 404

Fixes #446
2017-10-27 00:10:50 -07:00
Girish Ramakrishnan
d127b25f0f Only set the custom https agent for HTTPS minio
Otherwise, we get a Cannot set property ‘agent’ of undefined error
2017-10-26 18:38:45 -07:00
Johannes Zellner
6a2b0eedb3 Add ldap pagination support 2017-10-27 01:25:07 +02:00
Girish Ramakrishnan
8c81a97a4b Check that the backup location has perms to create a directory
The backup itself runs as root and this works fine. But when rotating
the backup, the copy fails because it is unable to create a directory.
2017-10-26 11:41:34 -07:00
Girish Ramakrishnan
d9ab1a78d5 Make the my location customizable
Fixes #22
2017-10-25 23:00:43 -07:00
Girish Ramakrishnan
593df8ed49 Do not use ADMIN_LOCATION in tests 2017-10-25 21:38:11 -07:00
Girish Ramakrishnan
b30def3620 move prerelease check to appstore 2017-10-25 21:34:56 -07:00
Johannes Zellner
9c02785d49 Support ldap group compare
Fixes #463
2017-10-24 02:00:00 +02:00
Johannes Zellner
f747343159 Cleanup unused port bindings after an update 2017-10-23 22:11:33 +02:00
Johannes Zellner
2971910ccf Do not accept port bindings on update route 2017-10-23 22:06:28 +02:00
Johannes Zellner
56534b9647 Add appdb.delPortBinding() 2017-10-23 22:05:43 +02:00
Johannes Zellner
a8d26067ee Allow autoupdates if new ports are added
Those will simply be disabled after update and the user has to
enable them through the app configuration
2017-10-20 22:27:48 +02:00
Johannes Zellner
4212e4bb00 Do not show any port binding update ui 2017-10-20 22:27:48 +02:00
Johannes Zellner
7b27ace7bf Update cloudron-setup help url 2017-10-20 22:13:54 +02:00
Girish Ramakrishnan
d8944da68d 1.7.5 changes 2017-10-19 12:19:10 -07:00
Girish Ramakrishnan
433d797cb7 Add SMTPS port for apps that require TLS connections for mail relay 2017-10-19 12:15:28 -07:00
Girish Ramakrishnan
0b1d940128 cloudscale -> cloudscale.ch 2017-10-19 07:28:07 -07:00
Johannes Zellner
6016024026 Move restore functions into appropriate scope object 2017-10-18 00:40:02 +02:00
Johannes Zellner
e199293229 Further reduce ui flickering on restore 2017-10-18 00:40:02 +02:00
Girish Ramakrishnan
2ebe92fec3 Do not chown mail directory 2017-10-16 23:18:37 -07:00
Girish Ramakrishnan
628cf1e3de bump mail container for superfluous sa-update supervisor file 2017-10-16 21:16:58 -07:00
Girish Ramakrishnan
9e9aaf68f0 No need to migrate mail data anymore 2017-10-16 21:13:57 -07:00
Girish Ramakrishnan
b595ca422c 1.7.4 changes 2017-10-16 15:28:36 -07:00
Girish Ramakrishnan
9273a6c726 Add option to disable hardlinks
We can probably remove this later based on the use
2017-10-16 15:22:40 -07:00
Johannes Zellner
76d00d4e65 Render changelog markdown as html in app update dialog 2017-10-17 00:07:58 +02:00
Johannes Zellner
668c03a11b Give visual feedback in the restore dialog when fetching backups 2017-10-16 22:31:49 +02:00
Girish Ramakrishnan
1e72d2d651 remove debugs (too noisy) 2017-10-16 12:34:09 -07:00
Girish Ramakrishnan
89fc8efc67 Save as empty array if find output is empty 2017-10-16 10:54:48 -07:00
Girish Ramakrishnan
241dbf160e Remove Unused required 2017-10-15 14:07:03 -07:00
Girish Ramakrishnan
e46bdc2caa Force the copy just like tar --overwrite 2017-10-13 23:23:36 -07:00
Girish Ramakrishnan
e1cb91ca76 bump mail container 2017-10-13 22:36:54 -07:00
Girish Ramakrishnan
709c742c46 Fix tests 2017-10-12 21:14:13 -07:00
Girish Ramakrishnan
ecad9c499c Port binding conflict can never happen in update route 2017-10-12 21:04:38 -07:00
Girish Ramakrishnan
ed0879ffcd Stop the app only after the backup completed
App backup can take a long time or possibly not work at all. For such
cases, do not stop the app or leave it in some errored state.

newConfigJson is the new config to be updated to. This ensures that
the db has correct app info during the update.
2017-10-12 18:10:41 -07:00
Girish Ramakrishnan
61e2878b08 save/restore exec bit in files
this covers the case where user might stash some executable files
that are used by plugins.
2017-10-12 16:18:11 -07:00
Girish Ramakrishnan
d97034bfb2 Follow backup format for box backups as well 2017-10-12 11:02:52 -07:00
Girish Ramakrishnan
21942552d6 Clarify the per-app backup flag 2017-10-12 11:02:52 -07:00
Girish Ramakrishnan
dd68c8f91f Various backup fixes 2017-10-12 11:02:48 -07:00
Girish Ramakrishnan
28ce5f41e3 handle errors in log stream 2017-10-11 12:55:56 -07:00
Girish Ramakrishnan
5694e676bd Set default rentention to a week 2017-10-11 12:55:55 -07:00
Girish Ramakrishnan
db8c5a116f Typo 2017-10-11 10:30:03 -07:00
Girish Ramakrishnan
fa39f0fbf3 Add 1.7.3 changes 2017-10-11 00:50:41 -07:00
Girish Ramakrishnan
1444bb038f only upload needs to be retried
copy/delete are already retried in the sdk code
2017-10-11 00:08:41 -07:00
Girish Ramakrishnan
ac9e421ecf improved backup progress and logging 2017-10-10 22:49:38 -07:00
Girish Ramakrishnan
b60cbe5a55 move constant 2017-10-10 19:47:21 -07:00
Girish Ramakrishnan
56d794745b Sprinkle retries in syncer logic 2017-10-10 14:25:03 -07:00
Girish Ramakrishnan
fd3b73bea2 typo in format name 2017-10-10 13:54:54 -07:00
Girish Ramakrishnan
78807782df Various hacks for exoscale-sos
SOS does not like multipart uploads. They just fail randomly.

As a fix, we try to detect filesystem files and skip multipart uploads
for files < 5GB. For > 5GB, we do multipart upload anyways (mostly fails).

The box backup is switched to flat-file for exoscale for the reason
above.
2017-10-10 11:03:20 -07:00
Girish Ramakrishnan
754b29b263 Start out empty if the previous run errored 2017-10-09 20:12:21 -07:00
Girish Ramakrishnan
9f97f48634 Add note on s3ForcePathStyle 2017-10-09 18:46:14 -07:00
Girish Ramakrishnan
815e5d9d9a graphs: Compute width of system graph from total memory
Fixes #452
2017-10-09 14:58:32 -07:00
Girish Ramakrishnan
91ec2eaaf5 sos: "/" must separate bucket and key name 2017-10-09 11:50:22 -07:00
Girish Ramakrishnan
f8d3a7cadd Bump mail container (fixes spam crash) 2017-10-06 16:45:21 -07:00
Girish Ramakrishnan
d04a09b015 Add note on bumping major infra version 2017-10-06 15:52:04 -07:00
Girish Ramakrishnan
5d997bcc89 Just mark DO Spaces as experimental instead 2017-10-06 14:45:14 -07:00
Girish Ramakrishnan
f0dd90a1f5 listObjectsV2 does not work on some S3 providers
specifically, cloudscale does not support it
2017-10-05 12:07:14 -07:00
Girish Ramakrishnan
ee8ee8e786 KeyCount is not set on some S3 providers 2017-10-05 11:36:54 -07:00
Girish Ramakrishnan
ee1a4411f8 Do not crash if prefix is empty string
('' || undefined) will return undefined ...
2017-10-05 11:08:01 -07:00
Girish Ramakrishnan
df6e6cb071 Allow s3 backend to accept self-signed certs
Fixes #316
2017-10-05 10:14:55 -07:00
Girish Ramakrishnan
ba5645a20e Disable DO spaces since it is not yet production ready 2017-10-05 09:21:26 -07:00
Girish Ramakrishnan
ca502a2d55 Display error code 2017-10-04 22:34:44 -07:00
Girish Ramakrishnan
ecd53b48db Display the backup format 2017-10-04 22:11:11 -07:00
Girish Ramakrishnan
b9efb0b50b Fix callback invokation 2017-10-04 19:28:40 -07:00
Johannes Zellner
3fb5034ebd Ensure we setup the correct OAuth redirectURI if altDomain is used 2017-10-05 01:10:25 +02:00
Girish Ramakrishnan
afed3f3725 Remove duplicate debug 2017-10-04 15:08:26 -07:00
Girish Ramakrishnan
b4f14575d7 Add 1.7.1 changes 2017-10-04 14:31:41 -07:00
Johannes Zellner
f437a1f48c Only allow dns setup with subdomain if enterprise query argument is provided 2017-10-04 22:25:14 +02:00
Girish Ramakrishnan
c3d7d867be Do not set logCallback 2017-10-04 12:32:12 -07:00
Girish Ramakrishnan
96c16cd5d2 remove debug 2017-10-04 11:54:17 -07:00
Girish Ramakrishnan
af182e3df6 caas: cache the creds, otherwise we bombard the server 2017-10-04 11:49:38 -07:00
Girish Ramakrishnan
d70ff7cd5b Make copy() return event emitter
This way the storage logic does not need to rely on progress
2017-10-04 11:02:50 -07:00
Johannes Zellner
38331e71e2 Ensure all S3 CopySource properties are URI encoded 2017-10-04 19:07:08 +02:00
Johannes Zellner
322a9a18d7 Use multipart copy for s3 and files larger than 5GB 2017-10-04 18:56:23 +02:00
Johannes Zellner
423ef546a9 Merge branch 'user_agent' into 'master'
Added user agent to health checks

See merge request !19
2017-10-04 11:48:02 +00:00
Dennis Schwerdel
e3f3241966 Added user agent to health checks 2017-10-04 13:05:00 +02:00
Johannes Zellner
eaef384ea5 Improve the invite link display
Fixes #445
2017-10-04 13:03:32 +02:00
Girish Ramakrishnan
b85bc3aa01 s3: Must encode copySource
https://github.com/aws/aws-sdk-js/issues/1302
2017-10-03 15:51:05 -07:00
Girish Ramakrishnan
01154d0ae6 s3: better error messages 2017-10-03 14:46:59 -07:00
Girish Ramakrishnan
6494050d66 Make removeDir less noisy 2017-10-03 01:22:37 -07:00
Girish Ramakrishnan
8c7223ceed Fix cleanup logic to use the app backup format
box backup and app backup can have different format
2017-10-03 00:56:34 -07:00
Girish Ramakrishnan
21afc71d89 add tests for storage backends 2017-10-02 23:08:16 -07:00
Girish Ramakrishnan
7bf70956a1 fix tests 2017-10-02 18:42:13 -07:00
Girish Ramakrishnan
9e9b8b095e Provider dhparams.pem to the mail container 2017-10-02 01:51:28 -07:00
Girish Ramakrishnan
0f543e6703 s3: add progress detail
this is a bit of a hack and we should add another way to set the progress
(maybe via backups.setProgress or via a progress callback). this is because
some methods like removeDir can be called from backuptask and from box code.
2017-10-01 18:25:51 -07:00
Girish Ramakrishnan
f9973e765c Add backup cleanup eventlog 2017-10-01 10:35:50 -07:00
Girish Ramakrishnan
e089851ae9 add debugs 2017-09-30 20:36:08 -07:00
Girish Ramakrishnan
c524d68c2f fix crash when cleaning up snapshots 2017-09-30 20:31:41 -07:00
Girish Ramakrishnan
5cccb50a31 fix backup cleanup logic 2017-09-30 18:38:45 -07:00
Girish Ramakrishnan
3d375b687a style: Fix quoting 2017-09-30 18:26:38 -07:00
Girish Ramakrishnan
a93d453963 rename flat-file to rsync
not a name I like but cannot come up with anything better

https://en.wikipedia.org/wiki/Flat_file_database

the term 'rsync format' seems to be used in a few places
2017-09-30 14:19:19 -07:00
Girish Ramakrishnan
f8ac2d4628 1.7.0 changes 2017-09-30 14:02:06 -07:00
Girish Ramakrishnan
d5ba73716b add emptydirs test 2017-09-29 15:29:22 -07:00
Girish Ramakrishnan
954224dafb make syncer track directories 2017-09-29 15:29:18 -07:00
Johannes Zellner
8b341e2bf8 Only make nginx listen on ipv6 connections if it is supported by the system
Could not decide on the ejs formatting, never nice for me
2017-09-29 19:43:37 +02:00
Johannes Zellner
78fb9401ee Add config.hasIPv6() 2017-09-29 19:43:37 +02:00
Girish Ramakrishnan
4a5cbab194 Do not remove parent directory in fs.remove()
Do the pruning in the cleanup logic instead
2017-09-28 20:55:45 -07:00
Girish Ramakrishnan
19999abc50 s3: fix restore 2017-09-28 14:35:49 -07:00
Girish Ramakrishnan
5123b669d7 remove options.concurrency 2017-09-28 12:20:15 -07:00
Girish Ramakrishnan
565c8445e1 make backup progress work for per-app backups 2017-09-28 11:17:48 -07:00
Girish Ramakrishnan
404a019c56 s3: Check IsTruncated before accessing Contents 2017-09-28 10:36:56 -07:00
Girish Ramakrishnan
24dee80aa6 Make box backups always tarball based
this makes cloudron easy to restore. in the future, if required,
we can move out the mail data as a separate virtual app backup
2017-09-28 10:22:10 -07:00
Girish Ramakrishnan
ce6df4bf96 Disable encryption for flat-file for now 2017-09-28 09:47:18 -07:00
Girish Ramakrishnan
f8f6c7d93e Add progress detail when rotating snapshots 2017-09-28 09:29:46 -07:00
Girish Ramakrishnan
bafc6dce98 s3: refactor out directory listing 2017-09-27 21:59:51 -07:00
Girish Ramakrishnan
56ee4d8e25 Remove old cache files when backup settings is changed 2017-09-27 21:04:46 -07:00
Girish Ramakrishnan
eeef221b4e Fix race where pipe finishes before file is created
When there are 0 length files, this is easily reproducible.
2017-09-27 19:40:26 -07:00
Girish Ramakrishnan
4674653982 compare size and inode as well 2017-09-27 19:39:03 -07:00
Girish Ramakrishnan
a34180c27b Add format to backupsdb
Call remove/removeDir based on the format
2017-09-27 18:02:30 -07:00
Girish Ramakrishnan
aa8ce2c62e Use graphite 0.12.0
this fixes an issue where carbon does not startup properly
if a previous pid file was present
2017-09-27 15:35:55 -07:00
Girish Ramakrishnan
b3c6b8aa15 do not spawn process just for chown 2017-09-27 15:07:19 -07:00
Girish Ramakrishnan
44a7a2579c rework backup status
* show backup progress even if not initiated by UI
* display backup progress in separate line
2017-09-27 15:07:15 -07:00
Girish Ramakrishnan
39f0e476f2 Start out empty if cache file is missing 2017-09-27 12:09:19 -07:00
Girish Ramakrishnan
003dc0dbaf Add todo 2017-09-27 11:50:49 -07:00
Girish Ramakrishnan
e39329218d Make tests work 2017-09-27 11:38:43 -07:00
Girish Ramakrishnan
8d3fbc5432 Save backup logs and fix backup progress 2017-09-26 21:09:00 -07:00
Girish Ramakrishnan
2780de631e writable streams emit finish 2017-09-26 16:43:51 -07:00
Girish Ramakrishnan
399c756735 use exec so that filenames do not have to be escaped 2017-09-26 15:53:42 -07:00
Girish Ramakrishnan
859311f9e5 Process delete commands before add commands
This is required for cases where a dir becomes a file (or vice-versa)
2017-09-26 15:33:54 -07:00
Girish Ramakrishnan
a9e89b57d9 merge caas storage into s3 backend 2017-09-26 12:28:33 -07:00
Girish Ramakrishnan
4e68abe51d Handle fs errors 2017-09-26 12:10:58 -07:00
Girish Ramakrishnan
12083f5608 Ignore all special files 2017-09-26 11:41:01 -07:00
Girish Ramakrishnan
d1efb2db56 remove bogus mkdir 2017-09-26 11:34:24 -07:00
Girish Ramakrishnan
adde28523f Add backup format to the backup UI 2017-09-26 10:46:02 -07:00
Girish Ramakrishnan
f122f46fe2 Generate new index file by appending to file 2017-09-26 07:57:20 -07:00
Girish Ramakrishnan
ad7fadb4a9 display backup id in the ui 2017-09-26 07:45:23 -07:00
Johannes Zellner
be383582e0 Do not rely on external resource in the appstatus page 2017-09-26 15:33:05 +02:00
Girish Ramakrishnan
0a60365143 Initial version of flat-file uploader 2017-09-26 00:17:11 -07:00
Girish Ramakrishnan
2f6cb3e913 set format in the backup ui 2017-09-26 00:01:36 -07:00
Girish Ramakrishnan
b0f85678d4 Implement downloadDir for flat-file format 2017-09-23 18:07:26 -07:00
Girish Ramakrishnan
e43413e063 implement remove dir in storage backends 2017-09-23 12:34:51 -07:00
Girish Ramakrishnan
e39a5c8872 preserve env in backuptask.js 2017-09-22 11:19:44 -07:00
Girish Ramakrishnan
fb4b75dd2a Fix typo in comment 2017-09-22 11:19:37 -07:00
Girish Ramakrishnan
3c1ccc5cf4 Add exoscale provider 2017-09-21 17:50:03 -07:00
Girish Ramakrishnan
abd66d6524 Add cloudscale as a provider 2017-09-21 17:49:26 -07:00
Girish Ramakrishnan
b61b7f80b5 Add DO spaces 2017-09-21 12:25:39 -07:00
Girish Ramakrishnan
efa850614d Add a s3-v4-compat provider 2017-09-21 12:13:45 -07:00
Girish Ramakrishnan
21c534c806 Ensure format is set in backupConfig 2017-09-21 09:49:55 -07:00
Girish Ramakrishnan
7e4ff2440c Fix text for manual DNS 2017-09-21 09:10:12 -07:00
Johannes Zellner
f415e19f6f Do not unneccesarily mention error in the logs
Not so friendly for log searches
2017-09-21 15:00:35 +02:00
Girish Ramakrishnan
97da8717ca Refactor backup strategy logic into backups.js 2017-09-20 14:09:55 -07:00
Girish Ramakrishnan
cbddb79d15 Resolve the id in rotateAppBackup 2017-09-20 09:38:55 -07:00
Johannes Zellner
bffb935f0f Also send digest to appstore account owner 2017-09-20 16:33:25 +02:00
Johannes Zellner
e50e0f730b Make nginx listen on :: for ipv6 2017-09-20 16:33:25 +02:00
Girish Ramakrishnan
26f33a8e9b Send resolved path to the storage APIs 2017-09-19 21:58:35 -07:00
Girish Ramakrishnan
952b1f6304 Make backuptask call back into backups.js 2017-09-19 20:27:49 -07:00
Girish Ramakrishnan
a3293c4c35 Fix tests 2017-09-19 12:43:13 -07:00
Girish Ramakrishnan
4892473eff backupIds do not have extension anymore
this code existed for legacy reasons
2017-09-19 12:34:09 -07:00
Girish Ramakrishnan
221d5f95e1 ensure backupFolder is always set 2017-09-19 12:34:09 -07:00
Girish Ramakrishnan
84649b9471 Bring back backuptask
This is required for various small reasons:

* dir iteration with a way to pass messagein back to the upload() easily
* can be killed independently of box code
* allows us to run sync (blocking) commands in the upload logic
2017-09-19 12:32:38 -07:00
Girish Ramakrishnan
44435559ab Typo 2017-09-19 10:37:45 -07:00
Girish Ramakrishnan
c351660a9a Implement backup rotation
Always upload to 'snapshot' dir and then rotate it. This will allow
us to keep pushing incrementally to 'snapshot' and do server side
rotations.
2017-09-18 21:17:34 -07:00
Girish Ramakrishnan
0a24130fd4 Just reset config instead of clearing cache 2017-09-18 19:41:15 -07:00
Girish Ramakrishnan
ea13f8f97e Fix checkInstall script 2017-09-18 18:19:27 -07:00
Johannes Zellner
d00801d020 Only require service account key for google dns on setup 2017-09-18 23:50:34 +02:00
Girish Ramakrishnan
8ced0aa78e copy: use hardlinks to preserve space 2017-09-18 14:29:48 -07:00
Girish Ramakrishnan
f5d32a9178 copyBackup -> copy 2017-09-18 14:29:15 -07:00
Girish Ramakrishnan
7fc45b3215 Refactor out the backup snapshot logic 2017-09-18 12:43:11 -07:00
Girish Ramakrishnan
9bed14a3e8 Enable IP6 in unbound
On some provider (https://www.nine.ch) disabling IPv6 makes unbound
not respond to the DNS queries.

Also, I was unable to test with prefer-ip6 to 'no' because unbound fails:

unbound[5657]: /etc/unbound/unbound.conf.d/cloudron-network.conf:8: error: unknown keyword 'no'
unbound[5657]: read /etc/unbound/unbound.conf failed: 3 errors in configuration file
2017-09-18 11:41:02 -07:00
Girish Ramakrishnan
71233ecd95 Fix undefined variable 2017-09-18 11:14:04 -07:00
Girish Ramakrishnan
02097298c6 Fix indentation 2017-09-18 10:38:30 -07:00
Girish Ramakrishnan
be03dd0821 remove unused require 2017-09-18 10:38:26 -07:00
Girish Ramakrishnan
5b77d2f0cf Add commented out debugging section for unbound 2017-09-18 10:38:22 -07:00
Girish Ramakrishnan
781f543e87 Rename API calls in the storage backend 2017-09-17 18:50:29 -07:00
Girish Ramakrishnan
6525a467a2 Rework backuptask into tar.js
This makes it easy to integrate another backup strategy
as the next step
2017-09-17 18:50:26 -07:00
Girish Ramakrishnan
6cddd61a24 Fix style 2017-09-17 18:50:23 -07:00
Girish Ramakrishnan
b0ee116004 targz: make sourceDir a string 2017-09-17 18:50:15 -07:00
Girish Ramakrishnan
867a59d5d8 Pull it all to left 2017-09-15 15:47:37 -07:00
Girish Ramakrishnan
6f5085ebc3 Downcase email 2017-09-15 15:45:26 -07:00
Johannes Zellner
e8a93dcb1b Add button to send test email
Fixes #419
2017-09-15 14:42:12 +02:00
Girish Ramakrishnan
09fe957cc7 style 2017-09-15 02:07:06 -07:00
Girish Ramakrishnan
020ccc8a99 gcdns: fix update/del confusion
in the DNS api, we always update/del all records of same type
2017-09-15 01:54:39 -07:00
Girish Ramakrishnan
7ed304bed8 Fix cloudflare domain display 2017-09-15 00:50:29 -07:00
Girish Ramakrishnan
db1e39be11 Do not overwrite subdomain when location was changed
* Install in subdomain 'test'
* Move to subdomain 'test2'
* Move to another existing subdomain 'www' (this should be detected as conflict)
* Move to subdomain 'www2' (this should not remove 'www'). This is why dnsRecordId exists.
2017-09-14 22:31:48 -07:00
Girish Ramakrishnan
f163577264 Typo 2017-09-14 18:38:48 -07:00
Girish Ramakrishnan
9c7080aea1 Show email text for gcdns 2017-09-14 18:33:07 -07:00
Girish Ramakrishnan
c05a7c188f Coding style fixes 2017-09-14 18:15:59 -07:00
Girish Ramakrishnan
72e912770a translate network errors to SubdomainError
fixes #391
2017-09-14 16:14:16 -07:00
Girish Ramakrishnan
28c06d0a72 bump mail container 2017-09-14 12:07:53 -07:00
Girish Ramakrishnan
9805daa835 Add google-cloud/dns to shrinkwrap 2017-09-14 10:45:04 -07:00
Girish Ramakrishnan
a920fd011c Merge branch 'feature/gcdns' into 'master'
Adding Google Cloud DNS support

See merge request !17
2017-09-14 17:44:20 +00:00
Girish Ramakrishnan
1b979ee1e9 Send rbl status as part of email check 2017-09-13 23:58:54 -07:00
Girish Ramakrishnan
70eae477dc Fix logstream test 2017-09-13 23:01:04 -07:00
Girish Ramakrishnan
c16f7c7891 Fix storage tests 2017-09-13 22:50:38 -07:00
Girish Ramakrishnan
63b8a5b658 Add update pattern of wednesday night
Fixes #432, #435
2017-09-13 14:52:31 -07:00
Aleksandr Bogdanov
c0bf51b79f A bit more polish 2017-09-13 21:17:40 +02:00
Aleksandr Bogdanov
3d4178b35c Adding Google Cloud DNS to "setupdns" stage 2017-09-13 21:00:29 +02:00
Aleksandr Bogdanov
34878bbc6a Make sure we don't touch records which are not managed by cloudron, but are in the same zone 2017-09-13 20:53:38 +02:00
Girish Ramakrishnan
e78d976c8f Fix backup mapping (mail dir has moved) 2017-09-13 09:51:20 -07:00
Girish Ramakrishnan
ba9662f3fa Add 1.6.5 changes 2017-09-12 22:32:57 -07:00
Girish Ramakrishnan
c8750a3bed merge the logrotate scripts 2017-09-12 22:03:24 -07:00
Girish Ramakrishnan
9710f74250 remove collectd stats when app is uninstalled 2017-09-12 21:34:15 -07:00
Girish Ramakrishnan
52095cb8ab add debugs for timing backup and restore 2017-09-12 15:37:35 -07:00
Aleksandr Bogdanov
c612966b41 Better validation 2017-09-12 22:47:46 +02:00
Aleksandr Bogdanov
90cf4f0784 Allowing to select a service account key as a file for gcdns 2017-09-12 22:35:40 +02:00
Aleksandr Bogdanov
ec93d564e9 Adding Google Cloud DNS to webadmin 2017-09-12 19:03:23 +02:00
Aleksandr Bogdanov
37f9e60978 Fixing verifyDns 2017-09-12 16:29:07 +02:00
Johannes Zellner
ca199961d5 Make settings.value field TEXT
We already store JSON blobs there and the gce dns backend
will require a larger blob for a certificate.
Since we use innodb the storage format in TEXT will only be different
if the data is large
2017-09-11 15:41:07 +02:00
Girish Ramakrishnan
fd811ac334 Remove "cloudron" to fit in one line 2017-09-10 17:43:21 -07:00
Girish Ramakrishnan
609c1d3b78 bump mail container
this is also required since we moved the maildir
2017-09-10 00:07:48 -07:00
Girish Ramakrishnan
9906ed37ae Move mail data inside boxdata directory
This also makes the noop backend more useful because it will dump things
in data directory and user can back it up as they see fit.
2017-09-10 00:07:44 -07:00
Girish Ramakrishnan
dcdce6d995 Use MAIL_DATA_DIR constant 2017-09-09 22:24:16 -07:00
Girish Ramakrishnan
9026c555f9 snapshots dir is not used anymore 2017-09-09 22:13:15 -07:00
Girish Ramakrishnan
547a80f17b make shell.exec options non-optional 2017-09-09 19:54:31 -07:00
Girish Ramakrishnan
300d3dd545 remove unused requires 2017-09-09 19:23:22 -07:00
Aleksandr Bogdanov
6fce729ed2 Adding Google Cloud DNS 2017-09-09 17:45:26 +02:00
Girish Ramakrishnan
d233ee2a83 ask password only for destructive actions 2017-09-08 15:14:37 -07:00
Girish Ramakrishnan
3240a71feb wording 2017-09-08 14:42:54 -07:00
Girish Ramakrishnan
322be9e5ba Add ip blacklist check
Fixes #431
2017-09-08 13:29:32 -07:00
Girish Ramakrishnan
e67ecae2d2 typo 2017-09-07 22:01:37 -07:00
Girish Ramakrishnan
75b3e7fc78 resolve symlinks correctly for deletion
part of #394
2017-09-07 21:57:08 -07:00
Girish Ramakrishnan
74c8d8cc6b set label on the redis container
this ensures that redis is stopped when app is stopped and also
helps identifying app related containers easily
2017-09-07 20:09:46 -07:00
Girish Ramakrishnan
51659a8d2d set label on the redis container
this ensures that redis is stopped when app is stopped and also
helps identifying app related containers easily
2017-09-07 19:54:05 -07:00
Girish Ramakrishnan
70acf1a719 Allow app volumes to be symlinked
The initial plan was to make app volumes to be set using a database
field but this makes the app backups non-portable. It also complicates
things wrt to app and server restores.

For now, ignore the problem and let them be symlinked.

Fixes #394
2017-09-07 15:50:34 -07:00
Girish Ramakrishnan
8d2f3b0217 Add note on disabling ssh password auth 2017-09-06 11:36:23 -07:00
Girish Ramakrishnan
e498678488 Use node 6.11.3 2017-09-06 09:39:22 -07:00
Girish Ramakrishnan
513517b15e cf dns: filter by type and name in the REST API
Otherwise, we will have to implement pagination
2017-09-05 16:07:14 -07:00
Girish Ramakrishnan
a96f8abaca DO DNS: list all pages of the domain 2017-09-05 15:52:59 -07:00
Johannes Zellner
f7bcd54ef5 Better ui feedback on the repair mode 2017-09-05 23:11:04 +02:00
Johannes Zellner
d58e4f58c7 Add hook to react whenever apps have changed 2017-09-05 23:10:45 +02:00
Girish Ramakrishnan
45f0f2adbe Fix wording 2017-09-05 10:38:33 -07:00
Johannes Zellner
36c72dd935 Sendgrid only has an api key similar postmark
Fixes #411
2017-09-05 11:28:28 +02:00
Girish Ramakrishnan
df9e2a7856 Use robotsTxt in install route 2017-09-04 12:59:14 -07:00
Girish Ramakrishnan
2b043aa95f remove unused require 2017-09-04 12:59:05 -07:00
Johannes Zellner
c0a09d1494 Add 1.6.4 changes 2017-09-04 18:53:11 +02:00
Johannes Zellner
1c5c4b5705 Improve overflow handling in logs and terminal view 2017-09-04 18:40:16 +02:00
Girish Ramakrishnan
b56dcaac68 Only run scheduler when app is healthy
Fixes #393
2017-09-03 18:21:13 -07:00
Girish Ramakrishnan
fd91ccc844 Update the unbound anchor key
This helps the unbound recover from any previous out of disk space
situation.

part of #269
2017-09-03 17:48:26 -07:00
Johannes Zellner
fca1a70eaa Add initial repair button alongside webterminal
Part of #416
2017-09-01 20:08:22 +02:00
Johannes Zellner
ed81b7890c Fixup the test for the password requirement change 2017-09-01 20:08:22 +02:00
Johannes Zellner
cb8dcbf3dd Lift the password requirement for app configure/update/restore actions 2017-09-01 20:08:22 +02:00
Johannes Zellner
4bdbf1f62e Fix indentation 2017-09-01 20:08:22 +02:00
Johannes Zellner
47a8b4fdc2 After consuming the accessToken query param, remove it
Fixes #415
2017-09-01 10:25:28 +02:00
Johannes Zellner
5720e90580 Guide the user to use ctrl+v for pasting into webterminal
Fixes #413
2017-08-31 20:52:04 +02:00
Johannes Zellner
f98e13d701 Better highlight dropdown menu hovers 2017-08-31 20:52:04 +02:00
Johannes Zellner
d5d924861b Fix gravatar margin in navbar 2017-08-31 20:52:04 +02:00
Girish Ramakrishnan
b81a92d407 disable ip6 in unbound as well
part of #412
2017-08-31 11:41:35 -07:00
Johannes Zellner
22b0100354 Ensure we don't crash if the terminal socket is not ready yet
Upstream patch submitted https://github.com/sourcelair/xterm.js/pull/933
2017-08-31 20:31:31 +02:00
Johannes Zellner
6eb6eab3f4 Let the browser handle paste keyboard shortcuts
Related to #413
2017-08-31 20:31:31 +02:00
Girish Ramakrishnan
57d5c2cc47 Use IPv4 address to connect to mysql
Fixes #412
2017-08-31 10:59:14 -07:00
Johannes Zellner
6a9eac7a24 Use the correct input change event
Fixes #414
2017-08-31 19:06:02 +02:00
Johannes Zellner
e4760a07f0 Give feedback if the relay settings have successfully saved 2017-08-30 11:02:13 +02:00
Johannes Zellner
257e594de0 Allow mail relay provider specific UI
Only contains specific UI for postmark

Part of #411
2017-08-30 10:55:36 +02:00
Girish Ramakrishnan
6fea022a04 remove dead code 2017-08-29 14:47:59 -07:00
Girish Ramakrishnan
f34840d127 remove old data migration paths 2017-08-29 13:08:31 -07:00
Girish Ramakrishnan
f9706d6a05 Always generate nginx config for webadmin
Part of #406
2017-08-28 21:16:47 -07:00
Girish Ramakrishnan
61f7c1af48 Remove unused error codes 2017-08-28 15:27:17 -07:00
Girish Ramakrishnan
00786dda05 Do not crash if DNS creds do not work during startup
If DNS creds are invalid, then platform.start() keeps crashing on a
mail container update. For now, just log the error and move on.

Part of #406
2017-08-28 14:55:36 -07:00
Girish Ramakrishnan
8b9f44addc 1.6.3 changes 2017-08-28 13:49:15 -07:00
Johannes Zellner
56c7dbb6e4 Do not attempt to reconnect if the debug view is already gone
Fixes #408
2017-08-28 21:06:25 +02:00
Girish Ramakrishnan
c47f878203 Set priority for MX records
Fixes #410
2017-08-26 15:54:38 -07:00
Girish Ramakrishnan
8a2107e6eb Show email text for Cloudflare 2017-08-26 15:37:24 -07:00
Girish Ramakrishnan
cd9f0f69d8 email dialog has moved to it's own view 2017-08-26 15:36:12 -07:00
Girish Ramakrishnan
1da91b64f6 Filter out possibly sensitive information for normal users
Fixes #407
2017-08-26 14:47:51 -07:00
Johannes Zellner
a87dd65c1d Workaround for firefox flexbox bug
Fixes selection while clicking on empty flexbox space.

This only happens in firefox and seems to be a bug in firefox
flexbox implementation, where the first child element with a
non zero size, in a flexbox managed `block` element, has the
`float` property.

Fixes #405
2017-08-24 23:29:42 +02:00
Johannes Zellner
7c63d9e758 Fix typo in css 2017-08-24 23:16:36 +02:00
Girish Ramakrishnan
329bf596ac Indicate that directories can be downloaded 2017-08-24 13:38:50 -07:00
Girish Ramakrishnan
2a57c4269a handle app not found 2017-08-23 13:23:04 -07:00
Girish Ramakrishnan
ca8813dce3 1.6.2 changes 2017-08-23 10:43:27 -07:00
Girish Ramakrishnan
3aebf51360 Fix upload of large files to apps
6a0ef7a1c1 broke the upload for apps

e2e test is being added
2017-08-23 10:22:54 -07:00
Johannes Zellner
103f8db8cb Do not expand to fixed pixel size on mobile 2017-08-23 16:57:34 +02:00
Johannes Zellner
04c127b78d Add changes for 1.6.1
Due to regressions we should skip 1.6.0 thus the same changelog
2017-08-23 16:14:30 +02:00
Johannes Zellner
9bef1bcf64 Hijack and demux the container exec stream to be compliant with new
dockerode
2017-08-23 16:04:50 +02:00
Johannes Zellner
718413c089 autocomplete attribute is not respected for username/password fields
Since the cloudflare email input field is above the password field
some browsers will automatically autofill it with the username
as it looks like a login form. So we add a hidden unused input field
which gets autofilled instead :-/
2017-08-23 13:13:00 +02:00
Girish Ramakrishnan
a34691df44 Hide the header as well 2017-08-22 09:30:18 -07:00
Girish Ramakrishnan
795e38fe82 file is an object 2017-08-22 09:15:46 -07:00
Johannes Zellner
1d348fb0f3 Do not lose focus on terminal 2017-08-22 16:24:26 +02:00
Johannes Zellner
91f3318879 Implement rightclick menu for terminal text copy 2017-08-22 16:23:06 +02:00
Girish Ramakrishnan
c61808f4c6 1.6.0 changes 2017-08-21 16:08:37 -07:00
Girish Ramakrishnan
991b2dad28 bump mail container version
part of #400
2017-08-21 15:54:21 -07:00
Girish Ramakrishnan
f3d9a70de7 Only send the stdout stream 2017-08-21 10:46:13 -07:00
Johannes Zellner
60758de10a Fixup package.json linter issues and clean the shrinkwrap 2017-08-21 12:45:15 +02:00
Girish Ramakrishnan
6a0ef7a1c1 Allow larger files to be uploaded
Note that other upload APIs like avatar are still limited to 1m by
the nginx config
2017-08-20 19:15:54 -07:00
Girish Ramakrishnan
7cb451c157 Allow dirs to downloaded as tarballs 2017-08-20 18:54:59 -07:00
Girish Ramakrishnan
3c31c96ad4 Hide the download dialog after download starts 2017-08-20 18:29:11 -07:00
Johannes Zellner
5d73f58631 Show upload progress 2017-08-20 19:32:00 +02:00
Johannes Zellner
4ca7cccdae Give error feedback if the requested file does not exist 2017-08-20 18:50:37 +02:00
Johannes Zellner
82380b6b7c Remove hardcoded /app/data and fix submit for file downloads 2017-08-20 18:09:43 +02:00
Johannes Zellner
979c4e77e3 Fix view bug when terminal reconnects but user has moved on 2017-08-20 18:00:07 +02:00
Johannes Zellner
e318fb0c01 Show restat button also in logs view 2017-08-20 17:57:32 +02:00
Girish Ramakrishnan
77d2fb97e5 test: create logrotate dir 2017-08-19 18:57:43 -07:00
Girish Ramakrishnan
24e6c4d963 bump test image 2017-08-19 17:57:21 -07:00
Girish Ramakrishnan
064c5cf7f2 Fix failing test 2017-08-19 17:41:15 -07:00
Girish Ramakrishnan
891542bfb9 move restart button 2017-08-19 17:33:59 -07:00
Girish Ramakrishnan
599702d410 Fix casing 2017-08-19 16:45:20 -07:00
Girish Ramakrishnan
3cb39754fd Make logs button work for apps 2017-08-19 12:52:48 -07:00
Girish Ramakrishnan
f04345a99a Move restart button to log view 2017-08-19 12:49:03 -07:00
Johannes Zellner
3d59b8a5b0 Deliver content-length and file not found errors for file downloads 2017-08-19 12:13:04 +02:00
Johannes Zellner
cf518b0285 Resize terminal based on initial DOM size
Currently we cannot send new cols,rows on DOM element resize
as they are sent on connect only and a reconnect would loose
current session
2017-08-19 11:32:00 +02:00
Girish Ramakrishnan
52832c881a Add upload and download for the webterminal 2017-08-18 21:19:48 -07:00
Girish Ramakrishnan
537fbff4aa Use ws directly to handle new exec ws route 2017-08-18 19:46:18 -07:00
Johannes Zellner
e3040b334d Do not submit injected commands right away but give some space and fix
focus
2017-08-18 20:36:52 +02:00
Johannes Zellner
6c2879d567 Rename debug view to terminal and logs 2017-08-18 20:36:47 +02:00
Johannes Zellner
595c89076f Add postgres, mongo and redis client injection 2017-08-18 11:26:10 -07:00
Johannes Zellner
c85f5b15c6 Reenable custom tcp upgrade handling 2017-08-18 11:26:05 -07:00
Johannes Zellner
8fbed7e84b Ensure we only write to the websocket if it is open 2017-08-18 11:26:00 -07:00
Johannes Zellner
ee3c5f67af Show mysql addon only if the app uses it 2017-08-18 11:25:54 -07:00
Johannes Zellner
52db28e876 Verify the websocket request 2017-08-18 11:25:49 -07:00
Johannes Zellner
65bc3491f6 enable timeout middleware again and reset it for all upgrade requests 2017-08-18 11:25:45 -07:00
Johannes Zellner
82f512dc27 Rename logs view to debug view 2017-08-18 11:25:37 -07:00
Johannes Zellner
4b41378d08 Ensure app restarts also close the websocket 2017-08-18 11:25:05 -07:00
Johannes Zellner
1fd4e27d92 Fix logs autoscroll 2017-08-18 11:25:00 -07:00
Johannes Zellner
2420fef6b1 Reconnect the terminal on disconnection
This can happen if the app crashes or restarts
2017-08-18 11:24:55 -07:00
Johannes Zellner
50074b936a Integrate the terminal with the logs ui 2017-08-18 11:24:48 -07:00
Johannes Zellner
f98e68edc1 Add express-ws node module 2017-08-18 11:24:42 -07:00
Johannes Zellner
83e5daf08c Add xterm.js 2017-08-18 11:24:34 -07:00
Girish Ramakrishnan
53b43ca36b Don't show restore button for noop backend 2017-08-17 20:20:06 -07:00
Girish Ramakrishnan
d11842a7f8 Show popup when using noop backend 2017-08-17 19:52:08 -07:00
Girish Ramakrishnan
6746781b46 Add warning for noop backend
Fixes #402
2017-08-17 12:38:52 -07:00
Girish Ramakrishnan
78ec8e5c0c Add field to skip backup for an app
This skips the app from a backup when doing a full box backup and
simply reuses the previous backup.

The app can still be explicitly backed up using 'cloudron backup'
and explicitly restored using 'cloudron restore --backup'.

When restoring the box, it all depends on the app's last backup.

Fixes #311
2017-08-16 16:36:50 -07:00
Johannes Zellner
67a2ba957e Use maxsize logrotate rule instead of size
The current ruleset means rotate the file daily unless the file grows
larger than 1Mb earlier, then rotate once the file reaches that size.

https://serverfault.com/questions/474941/how-to-rotate-log-based-on-an-interval-unless-log-exceeds-a-certain-size
2017-08-16 19:10:49 +02:00
Girish Ramakrishnan
9e558924bb df plugin replaces with _ and not -
Part of #348
2017-08-15 09:32:42 -07:00
Johannes Zellner
afcb3dd237 Fix layout issues in oauth views 2017-08-15 13:18:31 +02:00
Johannes Zellner
054de4813d Fix layout issue in update view 2017-08-15 11:04:47 +02:00
Girish Ramakrishnan
57891c64b5 use check_output instead
Aug 14 19:10:46 collectd[12651]: close failed in file object destructor:
Aug 14 19:10:46 collectd[12651]: IOError: [Errno 10] No child processes
2017-08-14 12:31:58 -07:00
Girish Ramakrishnan
26361c037d Merge branch 'mehdi/box-permissions'
Closes MR !14
2017-08-14 10:49:54 -07:00
Girish Ramakrishnan
2048b03431 Removed this file by mistake 2017-08-14 10:44:58 -07:00
Girish Ramakrishnan
c12aba6c00 install xfsprogs
on some VPS like scaleway this is not installed.

This is why docker with devicemapper was using ext4 and not devmapper

devmapper: XFS is not supported in your system. Either the kernel doesn't support it or mkfs.xfs is not in your PATH. Defaulting to ext4 filesystem"
2017-08-13 23:15:23 -07:00
Girish Ramakrishnan
0bd0857189 Update many modules
npm WARN deprecated ejs-cli@1.2.0: This has breaking change. (in ejs package) use <= 2.0.0.
npm WARN deprecated node-uuid@1.4.8: Use uuid module instead
npm WARN deprecated minimatch@0.3.0: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated minimatch@0.2.14: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated graceful-fs@1.2.3: graceful-fs v3.0.0 and before will fail on node releases >= v7.0. Please update to graceful-fs@^4.0.0 as soon as possible. Use 'npm ls graceful-fs' to find it in the tree.
2017-08-13 17:57:48 -07:00
Girish Ramakrishnan
978893250f Update superagent (for doubele callback bug) 2017-08-13 17:38:02 -07:00
mehdi
d0f4a76ca2 basic capabilities syntax 2017-08-12 09:42:54 +01:00
Girish Ramakrishnan
755c87b079 Remove extra space 2017-08-11 22:14:53 -07:00
Girish Ramakrishnan
1da073c9bf Display mail server settings inline 2017-08-11 22:12:11 -07:00
Girish Ramakrishnan
96ead77520 Remove the API section 2017-08-11 21:10:18 -07:00
Girish Ramakrishnan
178b04fead Fix broken links to docs 2017-08-11 21:00:51 -07:00
Girish Ramakrishnan
335631ac28 Look for log files in first level and third level as well 2017-08-11 16:24:56 -07:00
Girish Ramakrishnan
42778cb84d Add 1.5.0 changes 2017-08-11 16:24:30 -07:00
Johannes Zellner
2f51088e67 Add logrotate support for *.log files in /run mounts of apps
logrotate config files may contain arbitrary commands which are
exectued as root, thus the config files have to be owned by root.
This is the reason we need the sudo scripts :-/

To test the generated scripts, just run:
$ logrotate /etc/logrotate.conf -v

Fixes #396
2017-08-12 00:04:00 +02:00
Johannes Zellner
378d7aee91 Add docker.inspect() api 2017-08-11 23:31:59 +02:00
Johannes Zellner
ac53f8c747 Show app title for log selection 2017-08-11 15:32:58 +02:00
Girish Ramakrishnan
5fe73c5a46 Replace df plugin with custom df plugin
The built-in df plugin cannot do the following:
    * if we choose by type ext4, we want to skip devicemapper (on scaleway)
    * the MountPoint of the appsdata directory is not possible to know at install time

Fixes #398
2017-08-11 01:39:51 -07:00
Johannes Zellner
a6f13eee14 Fix further layout issues in the appstore login view 2017-08-11 09:30:07 +02:00
Girish Ramakrishnan
86d23a4d35 Switch default storage backend to overlay2
This does not try to migrate existing cloudrons from devicemapper.
We will possibly do that in a future version.

61e130fb7 takes care of checking that we run on ext4

https://cloudron.io/documentation/server/#using-overlay2-backend-for-docker

Fixes #364
2017-08-10 14:11:03 -07:00
Johannes Zellner
b25bb76792 Give some bottom spacing for the log output container 2017-08-10 21:49:27 +02:00
Johannes Zellner
7ba5d1e0d6 Enable automatic scrolling while trailing logs 2017-08-10 21:49:06 +02:00
Girish Ramakrishnan
f17bde2d97 Add motd message for cloudron admins about updates
Fixes #351
2017-08-10 12:14:51 -07:00
Girish Ramakrishnan
93cafebfdb Allow options to be set in shell.sudo and shell.exec 2017-08-09 19:32:02 -07:00
Johannes Zellner
5538a91585 We are not using bootstrap rows on toplevel layout anymore 2017-08-09 09:49:52 +02:00
Girish Ramakrishnan
09cb468290 Update node to 6.11.2 2017-08-08 18:41:38 -07:00
Johannes Zellner
3b98eb0543 Add cloudron logstream api test 2017-08-08 20:40:18 +02:00
Johannes Zellner
59936c6fbf Further simplification of the layout code 2017-08-08 18:24:00 +02:00
Johannes Zellner
5a7e636f2d Use flexbox to avoid lots of grid system quirks
Finally we can sanely control navbar and footer
2017-08-08 12:05:46 +02:00
Johannes Zellner
401dc37a50 Ensure we destroy the eventsource when the view changes 2017-08-08 11:52:32 +02:00
Johannes Zellner
9f1af572a0 Make log lines backlog configurable 2017-08-08 10:07:33 +02:00
Johannes Zellner
96e2fa159c Show timestamp in log lines 2017-08-08 09:55:18 +02:00
Johannes Zellner
bc49a3e18a Add moment.js to webadmin 2017-08-08 09:55:09 +02:00
Johannes Zellner
ae19d8d754 Protect the logs view from normal user access 2017-08-07 21:00:23 +02:00
Johannes Zellner
13b067eb88 Remove log download in support view
This has moved to the logs view
2017-08-07 20:54:18 +02:00
Johannes Zellner
af08f4e7b6 Auto scroll the log streamer 2017-08-07 19:43:07 +02:00
Johannes Zellner
534e5781ba Set correct font and fix the follow flag 2017-08-07 18:42:08 +02:00
Johannes Zellner
737e266729 Set the url for the log download button 2017-08-07 18:24:19 +02:00
Johannes Zellner
07a133ebe9 Fix the platform log streaming 2017-08-07 18:18:36 +02:00
Johannes Zellner
b0444edf7e Add platform logstream api 2017-08-07 17:09:39 +02:00
Johannes Zellner
bcf37d833f Allow to follow app logs 2017-08-07 16:48:27 +02:00
Johannes Zellner
e7db2ab137 Add color code to html conversion library 2017-08-07 16:47:47 +02:00
Johannes Zellner
125b416463 Add initial logs view 2017-08-07 13:50:45 +02:00
Girish Ramakrishnan
800468fbe6 Use debug instead 2017-08-04 11:16:00 -07:00
Girish Ramakrishnan
0c1e3ec6a0 use mailFqdn instead of adminFqdn 2017-08-04 07:46:09 -07:00
Johannes Zellner
d97ee5d425 Bring back update badge hover 2017-08-04 14:59:06 +02:00
Johannes Zellner
a1be30c35a Remove preceeding * or - in changelogs
Should be possibly solved somewhere more central
2017-08-04 12:31:25 +02:00
Johannes Zellner
ba3cb3b646 Do not crash the whole cloudron if an email template does not render but report the ejs error 2017-08-04 12:02:50 +02:00
Johannes Zellner
daadefe6b9 Ensure we also send the html portion of the digest mail 2017-08-04 12:00:01 +02:00
Girish Ramakrishnan
12c849398e 1.4.1 changes 2017-08-03 13:55:58 -07:00
Girish Ramakrishnan
392492be04 Only collect info on the / mountpoint
The original intention was to collect information on the data
dirs as well but we have long moved away from that design.
On some VPS like scaleway, this ends up collecting info on
devicemapper stuff (which are on ext4, not sure why).

In future, we should collect info of other disks as well (#348)

Fixes #389
2017-08-03 11:45:23 -07:00
Johannes Zellner
4fd0c3c66c Add html version of the digest email 2017-08-03 15:55:36 +02:00
Johannes Zellner
7d2e6d8d4d Add test_data for html email development 2017-08-03 15:55:03 +02:00
Girish Ramakrishnan
f3e7249bdc Fix unterminated quote 2017-08-02 14:43:05 -07:00
Johannes Zellner
53afb2606a Change the update notification badge 2017-08-02 21:45:11 +02:00
Girish Ramakrishnan
fbce71d031 Do not show the backup region for minio and exoscale
Fixes #392
2017-08-02 11:21:39 -07:00
Johannes Zellner
1adde7d8e8 And another doc links change to fit the new doc layout 2017-08-02 11:30:16 +02:00
Girish Ramakrishnan
d23599ba24 Add 1.1.3 2017-08-01 17:21:00 -07:00
Girish Ramakrishnan
ac35bcf9f0 add 1.0.x and 1.1.x changelogs 2017-08-01 16:48:51 -07:00
Johannes Zellner
e4c5dfda60 Adjust documentation links to fit knowledgebase 2017-08-01 20:38:47 +02:00
Johannes Zellner
99cfe564ae Add repair button to error dialog and improve dns error message 2017-08-01 11:56:39 +02:00
Johannes Zellner
70a3cdc9bc Make it more obvious that the error dialog can be triggered when clicking on the app icon 2017-08-01 11:56:39 +02:00
Girish Ramakrishnan
bd52068695 Return error object instead of false 2017-07-31 11:57:23 -07:00
Girish Ramakrishnan
ae54b57ca7 Fix wording to match cf website 2017-07-31 10:50:00 -07:00
Johannes Zellner
0eb3c26c05 Only show cloudflare note when cloudflare is selected 2017-07-31 17:01:04 +02:00
Johannes Zellner
ca007ff979 The Cloudflare token is called API Key 2017-07-31 11:46:17 +02:00
Johannes Zellner
2eb5c39388 Improve error reporting for cloudflare 2017-07-31 11:25:17 +02:00
Johannes Zellner
014ce9df66 Mention that we only support cloudflare DNS management 2017-07-31 11:08:17 +02:00
Johannes Zellner
a4dff215f1 Change eventlog db column types from JSON to TEXT
JSON type is only supported on oracle mysql and none of the features are
used
2017-07-31 09:44:30 +02:00
Girish Ramakrishnan
0db4387013 Ensure security updates are enabled
Fixes #346
2017-07-28 20:03:55 -07:00
Girish Ramakrishnan
d81abfb2f0 Add blocking flag to changes 2017-07-28 10:41:28 -07:00
Girish Ramakrishnan
0d880cf1e3 Add 1.4.0 changes 2017-07-28 10:39:33 -07:00
Girish Ramakrishnan
b24d600b31 Update haraka 2017-07-28 10:34:29 -07:00
Johannes Zellner
2ac52fc64f Merge branch 'issue102' into 'master'
Added support for cloudflare DNS

See merge request !8
2017-07-28 17:14:43 +00:00
Johannes Zellner
3bf07a3143 Make it work 2017-07-28 18:33:08 +02:00
Johannes Zellner
cf883046b3 verifyDnsConfig() api has changed 2017-07-28 16:33:19 +02:00
Johannes Zellner
5e9808ad79 We use single quotes 2017-07-28 16:12:41 +02:00
Johannes Zellner
83ddf0a62c add cloudflare ui components 2017-07-28 16:10:04 +02:00
Johannes Zellner
cb7fea97af Keep coding style consistent 2017-07-28 16:10:04 +02:00
Johannes Zellner
3a4ee3ec8c Check for cloudflare email and token 2017-07-28 16:10:04 +02:00
Johannes Zellner
96dbda3949 Provide cloudflare in dns setup screen 2017-07-28 16:10:04 +02:00
Johannes Zellner
7facf17ac6 Make cloudflare api available in subdomain.js 2017-07-28 16:10:04 +02:00
Johannes Zellner
a939367ab6 Cleanup linter errors 2017-07-28 16:10:04 +02:00
Abhishek Patil
fd52f0ded4 Added support cloudflare DNS TODO:UI
Signed-off-by: Abhishek Patil <abhishek@zeroth.me>
2017-07-28 16:10:04 +02:00
Johannes Zellner
84ba20493e The docs are now in a separate repo
See https://git.cloudron.io/cloudron/docs
2017-07-28 13:41:17 +02:00
Girish Ramakrishnan
4f9a9906c9 Do not automatically update apps with a major version change
(future) pre-1.0 packages can be considered 'experimental'

Fixes #342
2017-07-27 13:49:08 -07:00
Girish Ramakrishnan
204340eac0 Set ttl
Fixes #384
2017-07-27 13:25:37 -07:00
Girish Ramakrishnan
d72fffb61f Bump mail container for AUTH LOGIN crash fix 2017-07-27 13:21:37 -07:00
Girish Ramakrishnan
cf4f0af0be Freudian slip 2017-07-26 15:58:43 -07:00
Girish Ramakrishnan
07d0601342 doc: robots.txt 2017-07-26 15:48:16 -07:00
Johannes Zellner
4cd0e4d38d Fix digest cron schedule to no run every hour on wednesdays 2017-07-26 10:52:12 +02:00
Girish Ramakrishnan
4f1a596123 Add support for exoscale SOS 2017-07-25 15:23:04 -07:00
Girish Ramakrishnan
d3990eff39 Add 1.3.1 changelog 2017-07-25 09:34:43 -07:00
Girish Ramakrishnan
6eab8bbdce Use -%> for newline slurping
Fixes #383
2017-07-24 22:13:31 -07:00
Girish Ramakrishnan
61e130fb71 check that rootfs is ext4
part of #364
2017-07-24 18:14:53 -07:00
Johannes Zellner
0c2267f9b4 Allow digest to be templated with or without subscription 2017-07-24 21:15:28 +02:00
Girish Ramakrishnan
a4e822f1c0 multi-line changelog does not work :( 2017-07-23 21:15:11 -07:00
Girish Ramakrishnan
e9c5837059 Add 1.3.0 changes 2017-07-23 21:13:57 -07:00
Girish Ramakrishnan
17406e4560 Adjust digest wording 2017-07-23 21:07:13 -07:00
Girish Ramakrishnan
eb99f8b844 escape and quote the robotsTxt when templating
for now, we restrict the string length to 4096 since that is what
nginx allows
2017-07-23 19:56:28 -07:00
Johannes Zellner
4fec2fe124 Allow specify the robots.txt text in the configure dialog 2017-07-23 22:00:05 +02:00
Girish Ramakrishnan
4045eb7a33 Add digest tests 2017-07-23 10:58:00 -07:00
Johannes Zellner
99d8baf36f Add cron job to send email digest 2017-07-22 17:44:15 +02:00
Girish Ramakrishnan
db7a4b75ae log the host in nginx logs 2017-07-21 09:43:44 -07:00
Johannes Zellner
dcd8c82a75 send lastLogin event timestamp with alive status 2017-07-21 15:15:13 +02:00
Girish Ramakrishnan
d577756851 doc: formatting 2017-07-20 12:57:18 -07:00
Girish Ramakrishnan
1e9c1e6ed0 doc: subdomain installation 2017-07-20 12:37:42 -07:00
Girish Ramakrishnan
ecc76ed368 doc: mail relay 2017-07-20 11:40:03 -07:00
Girish Ramakrishnan
9e61f76aad doc: catch-all mailbox 2017-07-20 11:27:31 -07:00
Johannes Zellner
11c2cecc9e Ensure we only add a leading / when we have a prefix
Part of #343
2017-07-19 14:35:35 +02:00
Girish Ramakrishnan
b5aed7b00a Set full path for nginx access log 2017-07-18 21:49:12 -07:00
Girish Ramakrishnan
4d177e0d29 Add 1.3.0 changes 2017-07-18 21:21:24 -07:00
Girish Ramakrishnan
f070082586 doc: get/set mail from validation 2017-07-18 18:57:27 -07:00
Girish Ramakrishnan
f3483e6a92 fix typo in mail.ini 2017-07-18 17:38:21 -07:00
Girish Ramakrishnan
91e56223ce Add mail from validation tests
Fixes #366
2017-07-18 17:05:34 -07:00
Girish Ramakrishnan
631b830f4c Add setting to toggle from address validation check
part of #366
2017-07-18 16:33:42 -07:00
Girish Ramakrishnan
63364ae017 Use settings.getAll in createMailConfig 2017-07-18 13:50:39 -07:00
Girish Ramakrishnan
3b162c6648 Add _KEY prefix to catch all address 2017-07-18 13:50:05 -07:00
Girish Ramakrishnan
b4fb73934b Remove unused function 2017-07-18 13:42:22 -07:00
Girish Ramakrishnan
8f04163262 convert missing json settings in getAll 2017-07-18 13:31:43 -07:00
Girish Ramakrishnan
10b6664134 Update schema.sql 2017-07-18 12:03:45 -07:00
Girish Ramakrishnan
454ca86507 trigger a reconfigure to regenerate nginx configs
see !13
2017-07-18 11:38:02 -07:00
Girish Ramakrishnan
34020064bc Merge branch 'patch-1' into 'master'
add X-Forwarded-Port in nginx reverse proxy for jetpack

See merge request !13
2017-07-18 17:47:25 +00:00
Dick Tang
67486b8177 add X-Forwarded-Port in nginx reverse proxy for jetpack
jetpack require X-Forward for the port, or "requested method jetpack.jsonAPI does not exist"
ref: https://github.com/ViBiOh/docker-wordpress/issues/1
2017-07-18 15:58:46 +00:00
Girish Ramakrishnan
6a4be98f19 Display cloudronId in settings 2017-07-17 14:36:50 -07:00
Girish Ramakrishnan
d5fb048364 Bump test container version 2017-07-17 13:19:52 -07:00
Girish Ramakrishnan
6dd4d40692 parse and save zoneName to cloudron.conf
part of #377
2017-07-17 09:16:06 -07:00
Johannes Zellner
04d6f94108 Add docs for app migration 2017-07-17 15:28:06 +02:00
Johannes Zellner
8d49f5a229 Also put manually triggered app backups under a datetime prefix 2017-07-17 14:33:00 +02:00
Girish Ramakrishnan
f80713ba2f Make sure zoneName is not lost across updates
Part of #377
2017-07-16 11:05:04 -07:00
Girish Ramakrishnan
91f25465a4 Add 1.3.0 changes 2017-07-15 19:58:57 -05:00
Girish Ramakrishnan
aa5cc68301 Fix typo in error message 2017-07-15 19:58:52 -05:00
Girish Ramakrishnan
acd00222e5 Allow per-app configuration of robots.txt
https://developers.google.com/search/reference/robots_txt has
the specification

Part of #344
2017-07-14 15:25:05 -05:00
409 changed files with 32427 additions and 59404 deletions

3
.gitattributes vendored
View File

@@ -1,6 +1,7 @@
# following files are skipped when exporting using git archive
test export-ignore
docs export-ignore
.jshintrc export-ignore
.gitlab export-ignore
.gitattributes export-ignore
.gitignore export-ignore

1
.gitignore vendored
View File

@@ -1,7 +1,6 @@
node_modules/
coverage/
webadmin/dist/
setup/splash/website/
installer/src/certs/server.key
# vim swap files

View File

@@ -0,0 +1,6 @@
Please do not use this issue tracker for support requests and bug reports.
This issue tracker is used by the Cloudron development team to track actual
bugs in the code.
Please use the forum at https://forum.cloudron.io to report bugs. For
confidential issues, please email us at support@cloudron.io.

View File

@@ -0,0 +1,7 @@
Please do not use this issue tracker for support requests and feature reports.
This issue tracker is used by the Cloudron development team to track issues in
the code.
Please use the forum at https://forum.cloudron.io to report bugs. For
confidential issues, please email us at support@cloudron.io.

View File

@@ -2,6 +2,7 @@
"node": true,
"browser": true,
"unused": true,
"multistr": true,
"globalstrict": true,
"predef": [ "angular", "$" ],
"esnext": true

431
CHANGES
View File

@@ -888,10 +888,25 @@
[1.0.0]
* Make selfhosting great again
[1.0.1]
* Notification improvements
[1.0.2]
* Notification improvements
[1.1.0]
* Add support for email catch-all
* Support Cloudrons on subdomains
[1.1.1]
* Notification improvements
[1.1.2]
* Notification improvements
[1.1.3]
* Notification improvements
[1.2.0]
* Relay emails optionally via external SMTP server email (mailgun, sendgrid etc)
* (experimental) Preserver the docker storage driver across updates
@@ -902,3 +917,419 @@
* Fix issue where mail container does not cleanup LDAP connections properly
* Update node to 6.11.1
[1.3.0]
* Add option to configure robots.txt for each app from the web interface
* Make sure zoneName is not lost across updates
* Save manually triggered app backups under a datetime prefix
* Optionally disable FROM validation check in the mail container. This will allow apps to send emails with arbitrary FROM addresses
* Set X-Forwarded-Port in the reverse proxy. This fixes a problem with plugins of certain apps (like Jetpack)
* Send a weekly activity digest about pending and applied Cloudron and app updates
[1.4.0]
* (mail) Update Haraka to 2.8.14. Contains many stability fixes
* Exoscale SOS can now be used for backup storage
* Fix cron pattern that made Cloudron erroneously send out weekly digest mails every hour on wednesday
* Add Cloudflare DNS backend (thanks @abhishek)
* Ensure Cloudron is only be installed on EXT4 root file system (required by Docker)
* Mark app package major releases as blocking and require approval by Cloudron admin
[1.4.1]
* Do not display backup region when using minio and exoscale SOS
* Fix javascript error in email view
* Add html version of the digest email
* Fix issue where collectd was collecting information about devicemapper mounts
[1.5.0]
* Update node to 6.11.2
* Add a new view to display platform and app logs
* Rework web UI to use flexbox
* Add motd message to warn admins that to not run 'apt upgrade'
* Switch default storage backend for new Cloudrons to overlay2
* Add a custom graphite plugin to collect disk usage statistics
* Rotate logs of all apps automatically
[1.6.0]
* Allow apps to have 'network' capability (thanks @mehdi)
* Fix crash in collectd disk usage collection script
* Fix layout issues in update and oauth views
* Use maxsize rule instead of size in lograte configs
* Make it possible to skip backups per-app
* Hide restore button for noop backend
* Add popups and warnings for noop backend
* Add webterminal to shell into apps from the admin UI
* Update Haraka for a few crash fixes
[1.6.1]
* Patch release for 1.6.0 to fix regressions
* Allow apps to have 'network' capability (thanks @mehdi)
* Fix crash in collectd disk usage collection script
* Fix layout issues in update and oauth views
* Use maxsize rule instead of size in lograte configs
* Make it possible to skip backups per-app
* Hide restore button for noop backend
* Add popups and warnings for noop backend
* Add webterminal to shell into apps from the admin UI
* Update Haraka for a few crash fixes
[1.6.2]
* Allow apps to have 'network' capability (thanks @mehdi)
* Fix crash in collectd disk usage collection script
* Fix layout issues in update and oauth views
* Use maxsize rule instead of size in lograte configs
* Make it possible to skip backups per-app
* Hide restore button for noop backend
* Add popups and warnings for noop backend
* Add webterminal to shell into apps from the admin UI
* Update Haraka for a few crash fixes
[1.6.3]
* Fixes selection issue while clicking on empty flexbox space
* Indicate directories can be downloaded in the web terminal
* Do not show app update indicator for normal users
* Display email notice when using Cloudflare DNS
* Set MX records correctly when using Cloudflare DNS
* Fix bug where webterminal can incorrectly appear in main view
* Do not crash if DNS credentials are invalid
[1.6.4]
* More descriptive Postmark email relay form
* Fix file upload in chrome
* Support Ctrl/Cmd+v webterminal pasting
* Ensure unbound always starts up
* Add option to run app in repair mode
[1.6.5]
* DigitalOcean DNS: Add pagination
* Cloudflare DNS: Optimize listing of DNS entries
* Update node to 6.11.3
* App volumes can now be symlinked individually to external storage
* Periodically check if IP is blacklisted and notify admins
* Do not ask password when re-configuring app (since it is non-destructive)
* Move mail data inside boxdata directory. This makes the no-op backend more useful
* Remove collectd stats when app is uninstalled
[1.7.0]
* Add rsync format for backups. This feature allows incremental backups
* Add Google DNS backend (thanks @syn)
* Add DigitalOcean spaces backup storage backend
* Add Cloudscale and Exoscale as supported VPS providers
* Display backup progress and status in the web interface
* Preliminary IPv6 support
* Add IP RBL status to web interface
* Add auto-update pattern `Every wednesday night`
* Update Haraka to 2.8.15. This fixes the issue where emails were bounced with the message 'Send MAIL FROM first'
* Do not overwrite existing subdomain when app's location is changed
* Add button to send test email
* Fix crash in carbon which made graphs disappear on some Cloudrons
[1.7.1]
* Add rsync format for backups. This feature allows incremental backups
* Add Google DNS backend (thanks @syn)
* Add DigitalOcean spaces backup storage backend
* Add Cloudscale and Exoscale as supported VPS providers
* Display backup progress and status in the web interface
* Preliminary IPv6 support
* Add IP RBL status to web interface
* Add auto-update pattern `Every wednesday night`
* Update Haraka to 2.8.15. This fixes the issue where emails were bounced with the message 'Send MAIL FROM first'
* Do not overwrite existing subdomain when app's location is changed
* Add button to send test email
* Fix crash in carbon which made graphs disappear on some Cloudrons
[1.7.2]
* Add rsync format for backups. This feature allows incremental backups
* Add Google DNS backend (thanks @syn)
* Add Cloudscale and Exoscale as supported VPS providers
* Display backup progress and status in the web interface
* Preliminary IPv6 support
* Add IP RBL status to web interface
* Add auto-update pattern `Every wednesday night`
* Update Haraka to 2.8.15. This fixes the issue where emails were bounced with the message 'Send MAIL FROM first'
* Do not overwrite existing subdomain when app's location is changed
* Add button to send test email
* Fix crash in carbon which made graphs disappear on some Cloudrons
* Fix issue where OAuth SSO did not work when alternate domain was used
[1.7.3]
* Add rsync format for backups. This feature allows incremental backups
* Add Google DNS backend (thanks @syn)
* Add Cloudscale and Exoscale as supported VPS providers
* Display backup progress and status in the web interface
* Preliminary IPv6 support
* Add IP RBL status to web interface
* Add auto-update pattern `Every wednesday night`
* Update Haraka to 2.8.15. This fixes the issue where emails were bounced with the message 'Send MAIL FROM first'
* Do not overwrite existing subdomain when app's location is changed
* Add button to send test email
* Fix crash in carbon which made graphs disappear on some Cloudrons
* Fix issue where OAuth SSO did not work when alternate domain was used
[1.7.4]
* Add rsync format for backups. This feature allows incremental backups
* Add Google DNS backend (thanks @syn)
* Add DigitalOcean spaces backup storage backend
* Add Cloudscale and Exoscale as supported VPS providers
* Display backup progress and status in the web interface
* Preliminary IPv6 support
* Add IP RBL status to web interface
* Add auto-update pattern `Every wednesday night`
* Update Haraka to 2.8.15. This fixes the issue where emails were bounced with the message 'Send MAIL FROM first'
* Do not overwrite existing subdomain when app's location is changed
* Add button to send test email
* Fix crash in carbon which made graphs disappear on some Cloudrons
* Fix issue where OAuth SSO did not work when alternate domain was used
* Changelog is now rendered in markdown format
[1.7.5]
* Expose a TLS relay port from mail container for Go applications
[1.7.6]
* Port bindings cannot be configured in update route anymore
* Implement LDAP group compare
* Pre-releases are now offered by appstore and not handled in box code anymore
* LDAP pagination support. This will fix the warnings in NextCloud and Rocket.Chat
* Check if directories can be created in the backup directory
* Do not set the HTTPS agent when using HTTP with minio backup backend
* Fix regression where a new domain config could not be set in the UI
* New mail container release that fixes email sending with SOGo
* Show 404 page for unknown domains
[1.7.7]
* Allow setting app memory till memory limit
* Make the dkim selector dynamic
* Fix issue where app update dialog did not close
* Fix LE cert renewal failures
* Send user and cert info in digest emails
* Send oom, app failures and other important mails to cloudron owner's alt mail
[1.8.0]
* Fix group email bounce when a group has users that have not signed up yet
* Do not restrict app memory limit to 4GB
* Fix display of the latest backup in the weekly digest
* Add UI to select users for access restriction
* Update docker to 17.09
* Update node to 6.11.5
* Display package version of installed apps in the info dialog
[1.8.1]
* Update node modules
* Allow a restore operation if app is already restoring
* Remove pre-install bundle support since it was hardly used
* Make the test email mail address configurable
* Allow admins to access all apps
* Send feedback via appstore API (instead of email)
* Show documentation URL in the app info dialog
* Update Lets Encrypt agrement URL (https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf)
[1.8.2]
* Update node modules
* Allow a restore operation if app is already restoring
* Remove pre-install bundle support since it was hardly used
* Make the test email mail address configurable
* Allow admins to access all apps
* Send feedback via appstore API (instead of email)
* Show documentation URL in the app info dialog
* Update Lets Encrypt agrement URL (https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf)
[1.8.3]
* Ensure domain database record exists
[1.8.4]
* Fix issue where internal email was not delivered when email relay is enabled
* Fix display of DNS records when email relay is enabled
[1.8.5]
* Fix issues where unused addons were not cleaned on an app update causing uninstall to fail
* Change UI text from 'Waiting' to 'Pending'
[1.9.0]
* Prepare Cloudron for supporting multiple domains
* Add Cloudron restore UI
* Do not put app in errored state if backup fails
* Display backup progress in CaaS
* Add Google Cloud Storage backend for backups
* Update node to 8.9.3 LTS
* Set max email recepient limit (in outgoing emails) to 500
[1.9.1]
* Prepare Cloudron for supporting multiple domains
* Add Cloudron restore UI
* Do not put app in errored state if backup fails
* Display backup progress in CaaS
* Add Google Cloud Storage backend for backups
* Update node to 8.9.3 LTS
* Set max email recepient limit (in outgoing emails) to 500
* Put terminal and app logs viewer to separate window
[1.9.2]
* Prepare Cloudron for supporting multiple domains
* Add Cloudron restore UI
* Do not put app in errored state if backup fails
* Display backup progress in CaaS
* Add Google Cloud Storage backend for backups
* Update node to 8.9.3 LTS
* Set max email recepient limit (in outgoing emails) to 500
* Put terminal and app logs viewer to separate window
[1.9.3]
* Prepare Cloudron for supporting multiple domains
* Add Cloudron restore UI
* Do not put app in errored state if backup fails
* Display backup progress in CaaS
* Add Google Cloud Storage backend for backups
* Update node to 8.9.3 LTS
* Set max email recepient limit (in outgoing emails) to 500
* Put terminal and app logs viewer to separate window
[1.9.4]
* Fix typo causing LE cert renewals to fail
[1.10.0]
* Migrate mailboxes to support multiple domains
* Update addon containers to latest versions
* Add DigitalOcean Spaces region Singapore 1 (SGP1)
* Configure Exoscale SOS to use new SOS NG endpoint
* Fix S3 storage backend CopySource encoding rules
[1.10.1]
* Migrate mailboxes to support multiple domains
* Update addon containers to latest versions
* Add DigitalOcean Spaces region Singapore 1 (SGP1)
* Configure Exoscale SOS to use new SOS NG endpoint
* Fix S3 storage backend CopySource encoding rules
[1.10.2]
* Migrate mailboxes to support multiple domains
* Update addon containers to latest versions
* Add DigitalOcean Spaces region Singapore 1 (SGP1)
* Configure Exoscale SOS to use new SOS NG endpoint
* Fix S3 storage backend CopySource encoding rules
[1.11.0]
* Update Haraka to 2.8.17 to fix various crashes
* Report dependency error for clone if backup or domain was not found
* Enable auto-updates for major versions
[2.0.0]
* Multi-domain support
* Update Haraka to 2.8.18
* Split box and app autoupdate pattern settings
* Stop and disable any pre-installed postfix server
* Migrate altDomain as a manual DNS provider
* Use node's native dns resolve instead of dig
* DNS records can now be a A record or a CNAME record
* Fix generation of fallback certificates to include naked domain
* Merge multi-string DKIM records
* scheduler: do not start cron jobs all at once
* scheduler: give cron jobs a grace period of 30 minutes to complete
[2.0.1]
* Multi-domain support
* Update Haraka to 2.8.18
* Split box and app autoupdate pattern settings
* Stop and disable any pre-installed postfix server
* Migrate altDomain as a manual DNS provider
* Use node's native dns resolve instead of dig
* DNS records can now be a A record or a CNAME record
* Fix generation of fallback certificates to include naked domain
* Merge multi-string DKIM records
* scheduler: do not start cron jobs all at once
* scheduler: give cron jobs a grace period of 30 minutes to complete
* Rework the eventlog view
* App clone now clones the robotsTxt and backup settings
[2.1.0]
* Make S3 backend work reliably with slow internet connections
* Update docker to 18.03.0-ce
* Finalize the Email and Mailbox API
* Move mailbox settings from users to email view
* mail: fix issue where hosts with valid SPF for a Cloudron domain are unable to send mail to Cloudron
* mail: fix crash when bounce emails have a null sender
* Add CSP header for dashboard
* Add support for installing private docker images
[2.1.1]
* Make S3 backend work reliably with slow internet connections
* Update docker to 18.03.0-ce
* Finalize the Email and Mailbox API
* Move mailbox settings from users to email view
* mail: fix issue where hosts with valid SPF for a Cloudron domain are unable to send mail to Cloudron
* mail: fix crash when bounce emails have a null sender
* Add CSP header for dashboard
* Add support for installing private docker images
[2.2.0]
* Add 2FA support for the admin dashboard
* Cleanup scope management in REST API
* Enhance user creation API to take a password
* Relax restriction on mailbox names now that it is decoupled from user management
[2.2.1]
* Add 2FA support for the admin dashboard
* Add Gandi & GoDaddy DNS providers
* Fix zone detection logic on Route53 accounts with more than 100 zones
* Warn using when disabling email
* Cleanup scope management in REST API
* Enhance user creation API to take a password
* Relax restriction on mailbox names now that it is decoupled from user management
* Fix issue where mail container incorrectly advertised CRAM-MD5 support
[2.3.0]
* Add Name.com DNS provider
* Fix issue where account setup page was crashing
* Add advanced DNS configuration UI
* Preserve addon/database configuration across app updates and restores
* ManageSieve port now offers STARTTLS
[2.3.1]
* Add Name.com DNS provider
* Fix issue where account setup page was crashing
* Add advanced DNS configuration UI
* Preserve addon/database configuration across app updates and restores
* ManageSieve port now offers STARTTLS
* Allow mailbox name to be set for apps
* Rework the Email server UI
* Add the ability to manually trigger a backup of an application
* Enable/disable mail from validation within UI
* Allow setting app visibility for non-SSO apps
* Add Clone UI
[2.3.2]
* Fix issue where multi-db apps were not provisioned correctly
* Improve setup, restore views to have field labels
[2.4.0]
* Use custom logging backend to have more control over log rotation
* Make user explicitly confirm that fs backup dir is on external storage
* Update node to 8.11.2
* Update docker to 18.03.1
* Fix docker exec terminal resize issue
* Make the mailbox name follow the apps new location, if the user did not set it explicitly
* Add backups view
[2.4.1]
* Use custom logging backend to have more control over log rotation
* Mail logs and box logs UI
* Make user explicitly confirm that fs backup dir is on external storage
* Update node to 8.11.2
* Update docker to 18.03.1
* Fix docker exec terminal resize issue
* Make the mailbox name follow the apps new location, if the user did not set it explicitly
* Add backups view
[3.0.0]
* Support alternate app domains with redirects
* Allow hyphen in mailbox names
* Fix issue where the UI timesout when relay server is not reachable
* Add support for personal spaces
* Add UI to edit users in the groups dialog
* Add UI to set groups when creating a user
* Open logs and terminal in a new tab instead of a window
* Add button to view backup logs
* Add Mailjet mail relay support
* Encryption support for incremental backups
* Display restore errors in the UI
* Update Haraka to 2.8.19
* GPG verify releases
* Allow subdomains in location field

View File

@@ -630,7 +630,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
box
Copyright (C) 2016 Cloudron UG
Copyright (C) 2016,2017,2018 Cloudron UG
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published

View File

@@ -9,10 +9,6 @@ a complex task.
We are building the ultimate platform for self-hosting web apps. The Cloudron allows
anyone to effortlessly host web applications on their server on their own terms.
Support us on
[![Flattr Cloudron](https://button.flattr.com/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=cloudron&url=https://cloudron.io&title=Cloudron&tags=opensource&category=software)
or [pay us a coffee](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8982CKNM46D8U)
## Features
* Single click install for apps. Check out the [App Store](https://cloudron.io/appstore.html).
@@ -33,9 +29,9 @@ or [pay us a coffee](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_
* Trivially migrate to another server keeping your apps and data (for example, switch your
infrastructure provider or move to a bigger server).
* Comprehensive [REST API](https://cloudron.io/references/api.html).
* Comprehensive [REST API](https://cloudron.io/documentation/developer/api/).
* [CLI](https://git.cloudron.io/cloudron/cloudron-cli) to configure apps.
* [CLI](https://cloudron.io/documentation/cli/) to configure apps.
* Alerts, audit logs, graphs, dns management ... and much more
@@ -49,35 +45,25 @@ You can install the Cloudron platform on your own server or get a managed server
from cloudron.io. In either case, the Cloudron platform will keep your server and
apps up-to-date and secure.
* [Selfhosting](https://cloudron.io/references/selfhosting.html) - [Pricing](https://cloudron.io/pricing.html)
* [Selfhosting](https://cloudron.io/documentation/installation/) - [Pricing](https://cloudron.io/pricing.html)
* [Managed Hosting](https://cloudron.io/managed.html)
The wiki has instructions on how you can install and update the Cloudron and the
apps from source.
**Note:** This repo is a small part of what gets installed on your server - there is
the dashboard, database addons, graph container, base image etc. Cloudron also relies
on external services such as the App Store for apps to be installed. As such, don't
clone this repo and npm install and expect something to work.
## Documentation
* [User manual](https://cloudron.io/references/usermanual.html)
* [Developer docs](https://cloudron.io/documentation.html)
* [Architecture](https://cloudron.io/references/architecture.html)
* [Documentation](https://cloudron.io/documentation/)
## Related repos
The [base image repo](https://git.cloudron.io/cloudron/docker-base-image) is the parent image of all
the containers in the Cloudron.
The [graphite repo](https://git.cloudron.io/cloudron/docker-graphite) contains the graphite code
that collects metrics for graphs.
The addons are located in separate repositories
* [Redis](https://git.cloudron.io/cloudron/redis-addon)
* [Postgresql](https://git.cloudron.io/cloudron/postgresql-addon)
* [MySQL](https://git.cloudron.io/cloudron/mysql-addon)
* [Mongodb](https://git.cloudron.io/cloudron/mongodb-addon)
* [Mail](https://git.cloudron.io/cloudron/mail-addon)
## Community
* [Chat](https://chat.cloudron.io/)
* [Forum](https://forum.cloudron.io/)
* [Support](mailto:support@cloudron.io)

View File

@@ -29,7 +29,7 @@ function create_droplet() {
local ssh_key_id="$1"
local box_name="$2"
local image_region="sfo1"
local image_region="sfo2"
local ubuntu_image_slug="ubuntu-16-04-x64"
local box_size="1gb"

View File

@@ -39,13 +39,18 @@ apt-get -y install \
rcconf \
swaks \
unattended-upgrades \
unbound
unbound \
xfsprogs
# this ensures that unattended upgades are enabled, if it was disabled during ubuntu install time (see #346)
# debconf-set-selection of unattended-upgrades/enable_auto_updates + dpkg-reconfigure does not work
cp /usr/share/unattended-upgrades/20auto-upgrades /etc/apt/apt.conf.d/20auto-upgrades
echo "==> Installing node.js"
mkdir -p /usr/local/node-6.11.1
curl -sL https://nodejs.org/dist/v6.11.1/node-v6.11.1-linux-x64.tar.gz | tar zxvf - --strip-components=1 -C /usr/local/node-6.11.1
ln -sf /usr/local/node-6.11.1/bin/node /usr/bin/node
ln -sf /usr/local/node-6.11.1/bin/npm /usr/bin/npm
mkdir -p /usr/local/node-8.9.3
curl -sL https://nodejs.org/dist/v8.9.3/node-v8.9.3-linux-x64.tar.gz | tar zxvf - --strip-components=1 -C /usr/local/node-8.9.3
ln -sf /usr/local/node-8.9.3/bin/node /usr/bin/node
ln -sf /usr/local/node-8.9.3/bin/npm /usr/bin/npm
apt-get install -y python # Install python which is required for npm rebuild
[[ "$(python --version 2>&1)" == "Python 2.7."* ]] || die "Expecting python version to be 2.7.x"
@@ -54,16 +59,16 @@ echo "==> Installing Docker"
# create systemd drop-in file
mkdir -p /etc/systemd/system/docker.service.d
echo -e "[Service]\nExecStart=\nExecStart=/usr/bin/dockerd -H fd:// --log-driver=journald --exec-opt native.cgroupdriver=cgroupfs --storage-driver=devicemapper" > /etc/systemd/system/docker.service.d/cloudron.conf
echo -e "[Service]\nExecStart=\nExecStart=/usr/bin/dockerd -H fd:// --log-driver=journald --exec-opt native.cgroupdriver=cgroupfs --storage-driver=overlay2" > /etc/systemd/system/docker.service.d/cloudron.conf
curl -sL https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_17.03.1~ce-0~ubuntu-xenial_amd64.deb -o /tmp/docker.deb
curl -sL https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_18.03.1~ce-0~ubuntu_amd64.deb -o /tmp/docker.deb
# apt install with install deps (as opposed to dpkg -i)
apt install -y /tmp/docker.deb
rm /tmp/docker.deb
storage_driver=$(docker info | grep "Storage Driver" | sed 's/.*: //')
if [[ "${storage_driver}" != "devicemapper" ]]; then
echo "Docker is using "${storage_driver}" instead of devicemapper"
if [[ "${storage_driver}" != "overlay2" ]]; then
echo "Docker is using "${storage_driver}" instead of overlay2"
exit 1
fi
@@ -100,3 +105,7 @@ systemctl disable bind9 || true
systemctl stop dnsmasq || true
systemctl disable dnsmasq || true
# on ssdnodes postfix seems to run by default
systemctl stop postfix || true
systemctl disable postfix || true

View File

@@ -2,6 +2,8 @@
'use strict';
var database = require('./src/database.js');
var sendFailureLogs = require('./src/logcollector').sendFailureLogs;
function main() {
@@ -10,7 +12,12 @@ function main() {
var processName = process.argv[2];
console.log('Started crash notifier for', processName);
sendFailureLogs(processName, { unit: processName });
// mailer needs the db
database.initialize(function (error) {
if (error) return console.error('Cannot connect to database. Unable to send crash log.', error);
sendFailureLogs(processName, { unit: processName });
});
}
main();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

View File

@@ -1,319 +0,0 @@
# Overview
Addons are services like database, authentication, email, caching that are part of the
Cloudron runtime. Setup, provisioning, scaling and maintanence of addons is taken care of
by the runtime.
The fundamental idea behind addons is to allow sharing of Cloudron resources across applications.
For example, a single MySQL server instance can be used across multiple apps. The Cloudron
runtime sets up addons in such a way that apps are isolated from each other.
# Using Addons
Addons are opt-in and must be specified in the [Cloudron Manifest](/references/manifest.html).
When the app runs, environment variables contain the necessary information to access the addon.
For example, the mysql addon sets the `MYSQL_URL` environment variable which is the
connection string that can be used to connect to the database.
When working with addons, developers need to remember the following:
* Environment variables are subject to change every time the app restarts. This can happen if the
Cloudron is rebooted or restored or the app crashes or an addon is re-provisioned. For this reason,
applications must never cache the value of environment variables across restarts.
* Addons must be setup or updated on each application start up. Most applications use DB migration frameworks
for this purpose to setup and update the DB schema.
* Addons are configured in the [addons section](/references/manifest.html#addons) of the manifest as below:
```
{
...
"addons": {
"oauth": { },
"redis" : { }
}
}
```
# All addons
## email
This addon allows an app to send and recieve emails on behalf of the user. The intended use case is webmail applications.
If an app wants to send mail (e.g notifications), it must use the [sendmail](/references/addons#sendmail)
addon. If the app wants to receive email (e.g user replying to notification), it must use the
[recvmail](/references/addons#recvmail) addon instead.
Apps using the IMAP and ManageSieve services below must be prepared to accept self-signed certificates (this is not a problem
because these are addresses internal to the Cloudron).
Exported environment variables:
```
MAIL_SMTP_SERVER= # SMTP server IP or hostname. Supports STARTTLS (TLS upgrade is enforced).
MAIL_SMTP_PORT= # SMTP server port
MAIL_IMAP_SERVER= # IMAP server IP or hostname. TLS required.
MAIL_IMAP_PORT= # IMAP server port
MAIL_SIEVE_SERVER= # ManageSieve server IP or hostname. TLS required.
MAIL_SIEVE_PORT= # ManageSieve server port
MAIL_DOMAIN= # Domain of the mail server
```
## ldap
This addon provides LDAP based authentication via LDAP version 3.
Exported environment variables:
```
LDAP_SERVER= # ldap server IP
LDAP_PORT= # ldap server port
LDAP_URL= # ldap url of the form ldap://ip:port
LDAP_USERS_BASE_DN= # ldap users base dn of the form ou=users,dc=cloudron
LDAP_GROUPS_BASE_DN= # ldap groups base dn of the form ou=groups,dc=cloudron
LDAP_BIND_DN= # DN to perform LDAP requests
LDAP_BIND_PASSWORD= # Password to perform LDAP requests
```
For debugging, [cloudron exec](https://www.npmjs.com/package/cloudron) can be used to run the `ldapsearch` client within the context of the app:
```
cloudron exec
# list users
> ldapsearch -x -h "${LDAP_SERVER}" -p "${LDAP_PORT}" -b "${LDAP_USERS_BASE_DN}"
# list users with authentication (Substitute username and password below)
> ldapsearch -x -D cn=<username>,${LDAP_USERS_BASE_DN} -w <password> -h "${LDAP_SERVER}" -p "${LDAP_PORT}" -b "${LDAP_USERS_BASE_DN}"
# list admins
> ldapsearch -x -h "${LDAP_SERVER}" -p "${LDAP_PORT}" -b "${LDAP_USERS_BASE_DN}" "memberof=cn=admins,${LDAP_GROUPS_BASE_DN}"
# list groups
> ldapsearch -x -h "${LDAP_SERVER}" -p "${LDAP_PORT}" -b "${LDAP_GROUPS_BASE_DN}"
```
## localstorage
Since all Cloudron apps run within a read-only filesystem, this addon provides a writeable folder under `/app/data/`.
All contents in that folder are included in the backup. On first run, this folder will be empty. File added in this path
as part of the app's image (Dockerfile) won't be present. A common pattern is to create the directory structure required
the app as part of the app's startup script.
The permissions and ownership of data within that directory are not guranteed to be preserved. For this reason, each app
has to restore permissions as required by the app as part of the app's startup script.
If the app is running under the recommeneded `cloudron` user, this can be achieved with:
```
chown -R cloudron:cloudron /app/data
```
## mongodb
By default, this addon provide mongodb 2.6.3.
Exported environment variables:
```
MONGODB_URL= # mongodb url
MONGODB_USERNAME= # username
MONGODB_PASSWORD= # password
MONGODB_HOST= # server IP/hostname
MONGODB_PORT= # server port
MONGODB_DATABASE= # database name
```
For debugging, [cloudron exec](https://www.npmjs.com/package/cloudron) can be used to run the `mongo` shell within the context of the app:
```
cloudron exec
# mongo -u "${MONGODB_USERNAME}" -p "${MONGODB_PASSWORD}" ${MONGODB_HOST}:${MONGODB_PORT}/${MONGODB_DATABASE}
```
## mysql
By default, this addon provides a single database on MySQL 5.6.19. The database is already created and the application
only needs to create the tables.
Exported environment variables:
```
MYSQL_URL= # the mysql url (only set when using a single database, see below)
MYSQL_USERNAME= # username
MYSQL_PASSWORD= # password
MYSQL_HOST= # server IP/hostname
MYSQL_PORT= # server port
MYSQL_DATABASE= # database name (only set when using a single database, see below)
```
For debugging, [cloudron exec](https://www.npmjs.com/package/cloudron) can be used to run the `mysql` client within the context of the app:
```
cloudron exec
> mysql --user=${MYSQL_USERNAME} --password=${MYSQL_PASSWORD} --host=${MYSQL_HOST} ${MYSQL_DATABASE}
```
The `multipleDatabases` option can be set to `true` if the app requires more than one database. When enabled,
the following environment variables are injected:
```
MYSQL_DATABASE_PREFIX= # prefix to use to create databases
```
## oauth
The Cloudron OAuth 2.0 provider can be used in an app to implement Single Sign-On.
Exported environment variables:
```
OAUTH_CLIENT_ID= # client id
OAUTH_CLIENT_SECRET= # client secret
```
The callback url required for the OAuth transaction can be contructed from the environment variables below:
```
APP_DOMAIN= # hostname of the app
APP_ORIGIN= # origin of the app of the form https://domain
API_ORIGIN= # origin of the OAuth provider of the form https://my-cloudrondomain
```
OAuth2 URLs can be constructed as follows:
```
AuthorizationURL = ${API_ORIGIN}/api/v1/oauth/dialog/authorize # see above for API_ORIGIN
TokenURL = ${API_ORIGIN}/api/v1/oauth/token
```
The token obtained via OAuth has a restricted scope wherein they can only access the [profile API](/references/api.html#profile). This restriction
is so that apps cannot make undesired changes to the user's Cloudron.
We currently provide OAuth2 integration for Ruby [omniauth](https://git.cloudron.io/cloudron/omniauth-cloudron) and Node.js [passport](https://git.cloudron.io/cloudron/passport-cloudron).
## postgresql
By default, this addon provides PostgreSQL 9.4.4.
Exported environment variables:
```
POSTGRESQL_URL= # the postgresql url
POSTGRESQL_USERNAME= # username
POSTGRESQL_PASSWORD= # password
POSTGRESQL_HOST= # server name
POSTGRESQL_PORT= # server port
POSTGRESQL_DATABASE= # database name
```
The postgresql addon whitelists the hstore and pg_trgm extensions to be installable by the database owner.
For debugging, [cloudron exec](https://www.npmjs.com/package/cloudron) can be used to run the `psql` client within the context of the app:
```
cloudron exec
> PGPASSWORD=${POSTGRESQL_PASSWORD} psql -h ${POSTGRESQL_HOST} -p ${POSTGRESQL_PORT} -U ${POSTGRESQL_USERNAME} -d ${POSTGRESQL_DATABASE}
```
## recvmail
The recvmail addon can be used to receive email for the application.
Exported environment variables:
```
MAIL_IMAP_SERVER= # the IMAP server. this can be an IP or DNS name
MAIL_IMAP_PORT= # the IMAP server port
MAIL_IMAP_USERNAME= # the username to use for authentication
MAIL_IMAP_PASSWORD= # the password to use for authentication
MAIL_TO= # the "To" address to use
MAIL_DOMAIN= # the mail for which email will be received
```
The IMAP server only accepts TLS connections. The app must be prepared to accept self-signed certs (this is not a problem because the
imap address is internal to the Cloudron).
For debugging, [cloudron exec](https://www.npmjs.com/package/cloudron) can be used to run the `openssl` tool within the context of the app:
```
cloudron exec
> openssl s_client -connect "${MAIL_IMAP_SERVER}:${MAIL_IMAP_PORT}" -crlf
```
The IMAP command `? LOGIN username password` can then be used to test the authentication.
## redis
By default, this addon provides redis 2.8.13. The redis is configured to be persistent and data is preserved across updates
and restarts.
Exported environment variables:
```
REDIS_URL= # the redis url
REDIS_HOST= # server name
REDIS_PORT= # server port
REDIS_PASSWORD= # password
```
For debugging, [cloudron exec](https://www.npmjs.com/package/cloudron) can be used to run the `redis-cli` client within the context of the app:
```
cloudron exec
> redis-cli -h "${REDIS_HOST}" -p "${REDIS_PORT}" -a "${REDIS_PASSWORD}"
```
## scheduler
The scheduler addon can be used to run tasks at periodic intervals (cron).
Scheduler can be configured as below:
```
"scheduler": {
"update_feeds": {
"schedule": "*/5 * * * *",
"command": "/app/code/update_feed.sh"
}
}
```
In the above example, `update_feeds` is the name of the task and is an arbitrary string.
`schedule` values must fall within the following ranges:
* Minutes: 0-59
* Hours: 0-23
* Day of Month: 1-31
* Months: 0-11
* Day of Week: 0-6
_NOTE_: scheduler does not support seconds
`schedule` supports ranges (like standard cron):
* Asterisk. E.g. *
* Ranges. E.g. 1-3,5
* Steps. E.g. */2
`command` is executed through a shell (sh -c). The command runs in the same launch environment
as the application. Environment variables, volumes (`/tmp` and `/run`) are all
shared with the main application.
If a task is still running when a new instance of the task is scheduled to be started, the previous
task instance is killed.
## sendmail
The sendmail addon can be used to send email from the application.
Exported environment variables:
```
MAIL_SMTP_SERVER= # the mail server (relay) that apps can use. this can be an IP or DNS name
MAIL_SMTP_PORT= # the mail server port
MAIL_SMTP_USERNAME= # the username to use for authentication as well as the `from` username when sending emails
MAIL_SMTP_PASSWORD= # the password to use for authentication
MAIL_FROM= # the "From" address to use
MAIL_DOMAIN= # the domain name to use for email sending (i.e username@domain)
```
The SMTP server does not require STARTTLS. If STARTTLS is used, the app must be prepared to accept self-signed certs.
For debugging, [cloudron exec](https://www.npmjs.com/package/cloudron) can be used to run the `swaks` tool within the context of the app:
```
cloudron exec
> swaks --server "${MAIL_SMTP_SERVER}" -p "${MAIL_SMTP_PORT}" --from "${MAIL_SMTP_USERNAME}@${MAIL_DOMAIN}" --body "Test mail from cloudron app at $(hostname -f)" --auth-user "${MAIL_SMTP_USERNAME}" --auth-password "${MAIL_SMTP_PASSWORD}"
```

File diff suppressed because it is too large Load Diff

View File

@@ -1,87 +0,0 @@
# Introduction
The Cloudron platform is designed to easily install and run web applications.
The application architecture is designed to let the Cloudron take care of system
operations like updates, backups, firewalls, domain management, certificate management
etc. This allows app developers to focus on their application logic instead of deployment.
At a high level, an application provides an `image` and a `manifest`. The image is simply
a docker image that is a bundle of the application code and it's dependencies. The manifest
file specifies application runtime requirements like database type and authentication scheme.
It also provides meta information for display purposes in the [Cloudron Store](/appstore.html)
like the title, icon and pricing.
Web applications like blogs, wikis, password managers, code hosting, document editing,
file syncers, notes, email, forums are a natural fit for the Cloudron. Decentralized "social"
networks are also good app candidates for the Cloudron.
# Image
Application images are created using [Docker](https://www.docker.io). Docker provides a way
to package (and containerize) the application as a filesystem which contains it's code, system libraries
and just about anything the app requires. This flexible approach allows the application to use just
about any language or framework.
Application images are instantiated as `containers`. Cloudron can run one or more isolated instances
of the same application as one or more containers.
Containerizing your application provides the following benefits:
* Apps run in the familiar environment that they were packaged for and can have libraries
and packages that are independent of the host OS.
* Containers isolate applications from one another.
The [base image](/references/baseimage.html) is the parent of all app images.
# Cloudron Manifest
Each app provides a `CloudronManifest.json` that specifies information required for the
`Cloudron Store` and for the installation of the image in the Cloudron.
Information required for container installation includes:
* List of `addons` like databases, caches, authentication mechanisms and file systems
* The http port on which the container is listening for incoming requests
* Additional TCP ports on which the application is listening to (for e.g., git, ssh,
irc protocols)
Information required for the Cloudron Store includes:
* Unique App Id
* Title
* Version
* Logo
See the [manifest reference](/references/manifest.html) for more information.
# Addons
Addons are services like database, authentication, email, caching that are part of the
Cloudron. Setup, provisioning, scaling and maintenance of addons is taken care of by the
Cloudron.
The fundamental idea behind addons is to allow resource sharing across applications.
For example, a single MySQL server instance can be used across multiple apps. The Cloudron
sets up addons in such a way that apps are isolated from each other.
Addons are opt-in and must be specified in the Cloudron Manifest. When the app runs, environment
variables contain the necessary information to access the addon. See the
[addon reference](/references/addons.html) for more information.
# Authentication
The Cloudron provides a centralized dashboard to manage users, roles and permissions. Applications
do not create or manage user credentials on their own and instead use one of the various
authentication strategies provided by the Cloudron.
Authentication strategies include OAuth 2.0, LDAP or Simple Auth. See the
[Authentication Reference](/references/authentication.html) for more information.
Authorizing users is application specific and it is only authentication that is delegated to the
Cloudron.
# Cloudron App Library
Cloudron App Library provides a market place to publish your app.
Submitting to the app library enables any Cloudron user to discover and install your application with a few clicks.
# What next?
* [Package an existing app for the Cloudron](/tutorials/packaging.html)

View File

@@ -1,105 +0,0 @@
# Overview
Cloudron provides a centralized dashboard to manage users, roles and permissions. Applications
do not create or manage user credentials on their own and instead use one of the various
authentication strategies provided by the Cloudron.
Note that authentication only identifies a user and does not indicate if the user is authorized
to perform an action in the application. Authorizing users is application specific and must be
implemented by the application.
# Users & Admins
Cloudron user management is intentionally very simple. The owner (first user) of the
Cloudron is `admin` by default. The `admin` role allows one to install, uninstall and reconfigure
applications on the Cloudron.
A Cloudron `admin` can create one or more users. Cloudron users can login and use any of the installed
apps in the Cloudron. In general, adding a cloudron user is akin to adding a person from one's family
or organization or team because such users gain access to all apps in the Cloudron. Removing a user
immediately revokes access from all apps.
A Cloudron `admin` can give admin privileges to one or more Cloudron users.
Each Cloudron user has an unique `username` and an `email`.
# Strategies
Cloudron provides multiple authentication strategies.
* OAuth 2.0 provided by the [OAuth addon](/references/addons.html#oauth)
* LDAP provided by the [LDAP addon](/references/addons.html#ldap)
# Choosing a strategy
Applications can be broadly categorized based on their user management as follows:
* Multi-user aware
* Such apps have a full fledged user system and support multiple users and groups.
* These apps should use OAuth or LDAP.
* LDAP and OAuth APIs allow apps to detect if the user is a cloudron `admin`. Apps should use this flag
to show the application's admin panel for such users.
* No user
* Such apps have no concept of logged-in user.
* Single user
* Such apps only have a single user who is usually also the `admin`.
* These apps can use Simple Auth or LDAP since they can authenticate users with a simple HTTP or LDAP request.
* Such apps _must_ set the `singleUser` property in the manifest which will restrict login to a single user
(configurable through the Cloudron's admin panel).
# Public and Private apps
`Private` apps display content only when they have a signed-in user. These apps can choose one of the
authentication strategies listed above.
`Public` apps display content to any visiting user (e.g a blog). These apps have a `login` url to allow
the editors & admins to login. This path can be optionally set as the `configurePath` in the manifest for
discoverability (for example, some blogs hide the login link).
Some apps allow the user to choose `private` or `public` mode or some other combination. Such configuration
is done at app install time and cannot be changed using a settings interface. It is tempting to show the user
a configuration dialog on first installation to switch the modes. This, however, leads the user to believe that
this configuration can be changed at any time later. In the case where this setting can be changed dynamically
from a settings ui in the app, it's better to simply put some sensible defaults and let the user discover
the settings. In the case where such settings cannot be changed dynamically, it is best to simply publish two
separate apps in the Cloudron store each with a different configuration.
# External User Registration
Some apps allow external users to register and create accounts. For example, a public company chat that
can invite anyone to join or a blog allowing registered commenters.
Such applications must track Cloudron users and external registered users independently (for example, using a flag).
As a thumb rule, apps must provide separate login buttons for each of the possible user sources. Such a design prevents
external users from (inadvertently) spoofing Cloudron users.
Naively handling user registration enables attacks of the following kind:
* An external user named `foo` registers in the app.
* A LDAP user named `foo` is later created on the Cloudron.
* When a user named `foo` logs in, the app cannot determine the correct `foo` anymore. Making separate login buttons for each
login source clears the confusion for both the user and the app.
# Userid
The preferred approach to track users in an application is a uuid or the Cloudron `username`.
The `username` in Cloudron is unique and cannot be changed.
Tracking users using `email` field is error prone since that may be changed by the user anytime.
# Single Sign-on
Single sign-on (SSO) is a property where a user logged in one application automatically logs into
another application without having to re-enter his credentials. When applications implement the
OAuth strategy, they automatically take part in Cloudron SSO. When a user signs in one application with
OAuth, they will automatically log into any other app implementing OAuth.
Conversely, signing off from one app, logs them off from all the apps.
# Security
The LDAP and Simple Auth strategies require the user to provide their plain text passwords to the
application. This might be a cause of concern and app developers are thus highly encouraged to integrate
with OAuth. OAuth also has the advantage of supporting Single Sign On.

View File

@@ -1,94 +0,0 @@
# Overview
The application's Dockerfile must specify the FROM base image to be `cloudron/base:0.10.0`.
The base image already contains most popular software packages including node, nginx, apache,
ruby, PHP. Using the base image greatly reduces the size of app images.
The goal of the base image is simply to provide pre-downloaded software packages. The packages
are not configured in any way and it's up to the application to configure them as they choose.
For example, while `apache` is installed, there are no meaningful site configurations that the
application can use.
# Packages
The following packages are part of the base image. If you need another version, you will have to
install it yourself.
* Apache 2.4.18
* Composer 1.2.0
* Go 1.6.4, 1.7.5 (install under `/usr/local/go-<version>`)
* Gunicorn 19.4.5
* Java 1.8
* Maven 3.3.9
* Mongo 2.6.10
* MySQL Client 5.7.17
* nginx 1.10.0
* Node 0.10.48, 0.12.18, 4.7.3, 6.9.5 (installed under `/usr/local/node-<version>`) [more information](#node-js)
* Perl 5.22.1
* PHP 7.0.13
* Postgresql client 9.5.4
* Python 2.7.12
* Redis 3.0.6
* Ruby 2.3.1
* sqlite3 3.11.0
* Supervisor 3.2.0
* uwsgi 2.0.12
# Inspecting the base image
The base image can be inspected by installing [Docker](https://docs.docker.com/installation/).
Once installed, pull down the base image locally using the following command:
```
docker pull cloudron/base:0.10.0
```
To inspect the base image:
```
docker run -ti cloudron/base:0.10.0 /bin/bash
```
*Note:* Please use `docker 1.9.0` or above to pull the base image. Doing otherwise results in a base
image with an incorrect image id. The image id of `cloudron/base:0.10.0` is `5ec8ca8525be`.
# The `cloudron` user
The base image contains a user named `cloudron` that apps can use to run their app.
It is good security practice to run apps as a non-previleged user.
# Env vars
The following environment variables are set as part of the application runtime.
## API_ORIGIN
API_ORIGIN is set to the HTTP(S) origin of this Cloudron's API. For example,
`https://my-girish.cloudron.us`.
## APP_DOMAIN
APP_DOMAIN is set to the domain name of the application. For example, `app-girish.cloudron.us`.
## APP_ORIGIN
APP_ORIGIN is set to the HTTP(S) origin on the application. This is origin which the
user can use to reach the application. For example, `https://app-girish.cloudron.us`.
## CLOUDRON
CLOUDRON is always set to '1'. This is useful to write Cloudron specific code.
## WEBADMIN_ORIGIN
WEBADMIN_ORIGIN is set to the HTTP(S) origin of the Cloudron's web admin. For example,
`https://my-girish.cloudron.us`.
# Node.js
The base image comes pre-installed with various node.js versions.
They can be used by adding `ENV PATH /usr/local/node-<version>/bin:$PATH`.
See [Packages](/references/baseimage.html#packages) for available versions.

View File

@@ -1,47 +0,0 @@
# Cloudron Button
The `Cloudron Button` allows anyone to install an application with
the click of a button on their Cloudron.
The button can be added to just about any website including the application's website
and README.md files in GitHub repositories.
## Prerequisites
The `Cloudron Button` is intended to work only for applications that have been
published on the Cloudron Store. The [basic tutorial](/tutorials/basic.html#publishing)
gives an overview of how to package and publish your application for the
Cloudron Store.
## HTML Snippet
```
<img src="https://cloudron.io/img/button32.png" href="https://cloudron.io/button.html?app=<appid>">
```
_Note_: Replace `<appid>` with your application's id.
## Markdown Snippet
```
[![Install](https://cloudron.io/img/button32.png)](https://cloudron.io/button.html?app=<appid>)
```
_Note_: Replace `<appid>` with your application's id.
## Button Height
The button may be used in different heights - 32, 48 and 64 pixels.
[![Install](/img/button32.png)](https://cloudron.io/button.html?app=io.gogs.cloudronapp)
[![Install](/img/button48.png)](https://cloudron.io/button.html?app=io.gogs.cloudronapp)
[![Install](/img/button64.png)](https://cloudron.io/button.html?app=io.gogs.cloudronapp)
or as SVG
[![Install](/img/button.svg)](https://cloudron.io/button.html?app=io.gogs.cloudronapp)
_Note_: Clicking the buttons above will install [Gogs](http://gogs.io/) on your Cloudron.

View File

@@ -1,441 +0,0 @@
# Overview
Every Cloudron Application contains a `CloudronManifest.json`.
The manifest contains two categories of information:
* Information about displaying the app on the Cloudron Store. For example,
the title, author information, description etc
* Information for installing the app on the Cloudron. This includes fields
like httpPort, tcpPorts.
A CloudronManifest.json can **only** contain fields that are listed as part of this
specification. The Cloudron Store and the Cloudron *may* reject applications that have
extra fields.
Here is an example manifest:
```
{
"id": "com.example.test",
"title": "Example Application",
"author": "Girish Ramakrishnan <girish@cloudron.io>",
"description": "This is an example app",
"tagline": "A great beginning",
"version": "0.0.1",
"healthCheckPath": "/",
"httpPort": 8000,
"addons": {
"localstorage": {}
},
"manifestVersion": 1,
"website": "https://www.example.com",
"contactEmail": "support@clourdon.io",
"icon": "file://icon.png",
"tags": [ "test", "collaboration" ],
"mediaLinks": [ "https://images.rapgenius.com/fd0175ef780e2feefb30055be9f2e022.520x343x1.jpg" ]
}
```
# Fields
## addons
Type: object
Required: no
Allowed keys
* [email](addons.html#email)
* [ldap](addons.html#ldap)
* [localstorage](addons.html#localstorage)
* [mongodb](addons.html#mongodb)
* [mysql](addons.html#mysql)
* [oauth](addons.html#oauth)
* [postgresql](addons.html#postgresql)
* [recvmail](addons.html#recvmail)
* [redis](addons.html#redis)
* [sendmail](addons.html#sendmail)
The `addons` object lists all the [addons](addons.html) and the addon configuration used by the application.
Example:
```
"addons": {
"localstorage": {},
"mongodb": {}
}
```
## author
Type: string
Required: yes
The `author` field contains the name and email of the app developer (or company).
Example:
```
"author": "Cloudron UG <girish@cloudron.io>"
```
## changelog
Type: markdown string
Required: no (required for submitting to the Cloudron Store)
The `changelog` field contains the changes in this version of the application. This string
can be a markdown style bulleted list.
Example:
```
"changelog": "* Add support for IE8 \n* New logo"
```
## contactEmail
Type: email
Required: yes
The `contactEmail` field contains the email address that Cloudron users can contact for any
bug reports and suggestions.
Example:
```
"contactEmail": "support@testapp.com"
```
## description
Type: markdown string
Required: yes
The `description` field contains a detailed description of the app. This information is shown
to the user when they install the app from the Cloudron Store.
Example:
```
"description": "This is a detailed description of this app."
```
A large `description` can be unweildy to manage and edit inside the CloudronManifest.json. For
this reason, the `description` can also contain a file reference. The Cloudron CLI tool fills up
the description from this file when publishing your application.
Example:
```
"description:": "file://DESCRIPTION.md"
```
## healthCheckPath
Type: url path
Required: yes
The `healthCheckPath` field is used by the Cloudron Runtime to determine if your app is running and
responsive. The app must return a 2xx HTTP status code as a response when this path is queried. In
most cases, the default "/" will suffice but there might be cases where periodically querying "/"
is an expensive operation. In addition, the app might want to use a specialized route should it
want to perform some specialized internal checks.
Example:
```
"healthCheckPath": "/"
```
## httpPort
Type: positive integer
Required: yes
The `httpPort` field contains the TCP port on which your app is listening for HTTP requests. This
is the HTTP port the Cloudron will use to access your app internally.
While not required, it is good practice to mark this port as `EXPOSE` in the Dockerfile.
Cloudron Apps are containerized and thus two applications can listen on the same port. In reality,
they are in different network namespaces and do not conflict with each other.
Note that this port has to be HTTP and not HTTPS or any other non-HTTP protocol. HTTPS proxying is
handled by the Cloudron platform (since it owns the certificates).
Example:
```
"httpPort": 8080
```
## icon
Type: local image filename
Required: no (required for submitting to the Cloudron Store)
The `icon` field is used to display the application icon/logo in the Cloudron Store. Icons are expected
to be square of size 256x256.
```
"icon": "file://icon.png"
```
## id
Type: reverse domain string
Required: yes
The `id` is a unique human friendly Cloudron Store id. This is similar to reverse domain string names used
as java package names. The convention is to base the `id` based on a domain that you own.
The Cloudron tooling allows you to build applications with any `id`. However, you will be unable to publish
the application if the id is already in use by another application.
```
"id": "io.cloudron.testapp"
```
## manifestVersion
Type: integer
Required: yes
`manifestVersion` specifies the version of the manifest and is always set to 1.
```
"manifestVersion": 1
```
## mediaLinks
Type: array of urls
Required: no (required for submitting to the Cloudron Store)
The `mediaLinks` field contains an array of links that the Cloudron Store uses to display a slide show of pictures of the application.
They have to be publicly reachable via `https` and should have an aspect ratio of 3 to 1.
For example `600px by 200px` (with/height).
```
"mediaLinks": [
"https://s3.amazonaws.com/cloudron-app-screenshots/org.owncloud.cloudronapp/556f6a1d82d5e27a7c4fca427ebe6386d373304f/2.jpg",
"https://images.rapgenius.com/fd0175ef780e2feefb30055be9f2e022.520x343x1.jpg"
]
```
## memoryLimit
Type: bytes (integer)
Required: no
The `memoryLimit` field is the maximum amount of memory (including swap) in bytes an app is allowed to consume before it
gets killed and restarted.
By default, all apps have a memoryLimit of 256MB. For example, to have a limit of 500MB,
```
"memoryLimit": 524288000
```
## maxBoxVersion
Type: semver string
Required: no
The `maxBoxVersion` field is the maximum box version that the app can possibly run on. Attempting to install the app on
a box greater than `maxBoxVersion` will fail.
This is useful when a new box release introduces features which are incompatible with the app. This situation is quite
unlikely and it is recommended to leave this unset.
## minBoxVersion
Type: semver string
Required: no
The `minBoxVersion` field is the minimum box version that the app can possibly run on. Attempting to install the app on
a box lesser than `minBoxVersion` will fail.
This is useful when the app relies on features that are only available from a certain version of the box. If unset, the
default value is `0.0.1`.
## postInstallMessage
Type: markdown string
Required: no
The `postInstallMessageField` is a message that is displayed to the user after an app is installed.
The intended use of this field is to display some post installation steps that the user has to carry out to
complete the installation. For example, displaying the default admin credentials and informing the user to
to change it.
The message can have the following special tags:
* `<sso> ... </sso>` - Content in `sso` blocks are shown if SSO enabled.
* `<nosso> ... </nosso>`- Content in `nosso` blocks are shows when SSO is disabled.
## optionalSso
Type: boolean
Required: no
The `optionalSso` field can be set to true for apps that can be installed optionally without using the Cloudron user management.
This only applies if any Cloudron auth related addons are used. When set, the Cloudron will not inject the auth related addon environment variables.
Any app startup scripts have to be able to deal with missing env variables in this case.
## tagline
Type: one-line string
Required: no (required for submitting to the Cloudron Store)
The `tagline` is used by the Cloudron Store to display a single line short description of the application.
```
"tagline": "The very best note keeper"
```
## tags
Type: Array of strings
Required: no (required for submitting to the Cloudron Store)
The `tags` are used by the Cloudron Store for filtering searches by keyword.
```
"tags": [ "git", "version control", "scm" ]
```
## targetBoxVersion
Type: semver string
Required: no
The `targetBoxVersion` field is the box version that the app was tested on. By definition, this version has to be greater
than the `minBoxVersion`.
The box uses this value to enable compatibility behavior of APIs. For example, an app sets the targetBoxVersion to 0.0.5
and is published on the store. Later, box version 0.0.10 introduces a new feature that conflicts with how apps used
to run in 0.0.5 (say SELinux was enabled for apps). When the box runs such an app, it ensures compatible behavior
and will disable the SELinux feature for the app.
If unspecified, this value defaults to `minBoxVersion`.
## tcpPorts
Type: object
Required: no
Syntax: Each key is the environment variable. Each value is an object containing `title`, `description` and `defaultValue`.
An optional `containerPort` may be specified.
The `tcpPorts` field provides information on the non-http TCP ports/services that your application is listening on. During
installation, the user can decide how these ports are exposed from their Cloudron.
For example, if the application runs an SSH server at port 29418, this information is listed here. At installation time,
the user can decide any of the following:
* Expose the port with the suggested `defaultValue` to the outside world. This will only work if no other app is being exposed at same port.
* Provide an alternate value on which the port is to be exposed to outside world.
* Disable the port/service.
To illustrate, the application lists the ports as below:
```
"tcpPorts": {
"SSH_PORT": {
"title": "SSH Port",
"description": "SSH Port over which repos can be pushed & pulled",
"defaultValue": 29418,
"containerPort": 22
}
},
```
In the above example:
* `SSH_PORT` is an app specific environment variable. Only strings, numbers and _ (underscore) are allowed. The author has to ensure that they don't clash with platform profided variable names.
* `title` is a short one line information about this port/service.
* `description` is a multi line description about this port/service.
* `defaultValue` is the recommended port value to be shown in the app installation UI.
* `containerPort` is the port that the app is listening on (recall that each app has it's own networking namespace).
In more detail:
* If the user decides to disable the SSH service, this environment variable `SSH_PORT` is absent. Applications _must_ detect this on
start up and disable these services.
* `SSH_PORT` is set to the value of the exposed port. Should the user choose to expose the SSH server on port 6000, then the
value of SSH_PORT is 6000.
* `defaultValue` is **only** used for display purposes in the app installation UI. This value is independent of the value
that the app is listening on. For example, the app can run an SSH server at port 22 but still recommend a value of 29418 to the user.
* `containerPort` is the port that the app is listening on. The Cloudron runtime will _bridge_ the user chosen external port
with the app specific `containerPort`. Cloudron Apps are containerized and each app has it's own networking namespace.
As a result, different apps can have the same `containerPort` value because these values are namespaced.
* The environment variable `SSH_PORT` may be used by the app to display external URLs. For example, the app might want to display
the SSH URL. In such a case, it would be incorrect to use the `containerPort` 22 or the `defaultValue` 29418 since this is not
the value chosen by the user.
* `containerPort` is optional and can be omitted, in which case the bridged port numbers are the same internally and externally.
Some apps use the same variable (in their code) for listen port and user visible display strings. When packaging these apps,
it might be simpler to listen on `SSH_PORT` internally. In such cases, the app can omit the `containerPort` value and should
instead reconfigure itself to listen internally on `SSH_PORT` on each start up.
## title
Type: string
Required: yes
The `title` is the primary application title displayed on the Cloudron Store.
Example:
```
"title": "Gitlab"
```
## version
Type: semver string
Required: yes
The `version` field specifies a [semver](http://semver.org/) string. The version is used by the Cloudron to compare versions and to
determine if an update is available.
Example:
```
"version": "1.1.0"
```
## website
Type: url
Required: yes
The `website` field is a URL where the user can read more about the application.
Example:
```
"website": "https://example.com/myapp"
```

View File

@@ -1,61 +0,0 @@
# Configuration Recipes
## nginx
`nginx` is often used as a reverse proxy in front of the application, to dispatch to different backend programs based on the request route or other characteristics. In such a case it is recommended to run nginx and the application through a process manager like `supervisor`.
Example nginx supervisor configuration file:
```
[program:nginx]
directory=/tmp
command=/usr/sbin/nginx -g "daemon off;"
user=root
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
```
The nginx configuration, provided with the base image, can be used by adding an application specific config file under `/etc/nginx/sites-enabled/` when building the docker image.
```
ADD <app config file> /etc/nginx/sites-enabled/<app config file>
```
Since the base image nginx configuration is unpatched from the ubuntu package, the application configuration has to ensure nginx is using `/run/` instead of `/var/lib/nginx/` to support the read-only filesystem nature of a Cloudron application.
Example nginx app config file:
```
client_body_temp_path /run/client_body;
proxy_temp_path /run/proxy_temp;
fastcgi_temp_path /run/fastcgi_temp;
scgi_temp_path /run/scgi_temp;
uwsgi_temp_path /run/uwsgi_temp;
server {
listen 8000;
root /app/code/dist;
location /api/v1/ {
proxy_pass http://127.0.0.1:8001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
}
```
## supervisor
Use this in the program's config:
```
[program:app]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
```

View File

@@ -1,510 +0,0 @@
# Overview
The Cloudron platform can be installed on public cloud servers from EC2, Digital Ocean, Hetzner,
Linode, OVH, Scaleway, Vultr etc. Cloudron also runs well on a home server or company intranet.
If you run into any trouble following this guide, ask us at our [chat](https://chat.cloudron.io).
# Understand
Before installing the Cloudron, it is helpful to understand Cloudron's design. The Cloudron
intends to make self-hosting effortless. It takes care of updates, backups, firewall, dns setup,
certificate management etc. All app and user configuration is carried out using the web interface.
This approach to self-hosting means that the Cloudron takes complete ownership of the server and
only tracks changes that were made via the web interface. Any external changes made to the server
(i.e other than via the Cloudron web interface or API) may be lost across updates.
The Cloudron requires a domain name when it is installed. Apps are installed into subdomains.
The `my` subdomain is special and is the location of the Cloudron web interface. For this to
work, the Cloudron requires a way to programmatically configure the DNS entries of the domain.
Note that the Cloudron will never overwrite _existing_ DNS entries and refuse to install
apps on existing subdomains (so, it is safe to reuse an existing domain that runs other services).
# Cloud Server
DigitalOcean and EC2 (Amazon Web Services) are frequently tested by us.
Please use the below links to support us with referrals:
* [Amazon EC2](https://aws.amazon.com/ec2/)
* [DigitalOcean](https://m.do.co/c/933831d60a1e)
In addition to those, the Cloudron community has successfully installed the platform on those providers:
* [Amazon Lightsail](https://amazonlightsail.com/)
* [hosttech](https://www.hosttech.ch/?promocode=53619290)
* [Linode](https://www.linode.com/?r=f68d816692c49141e91dd4cef3305da457ac0f75)
* [OVH](https://www.ovh.com/)
* [Rosehosting](https://secure.rosehosting.com/clientarea/?affid=661)
* [Scaleway](https://www.scaleway.com/)
* [So you Start](https://www.soyoustart.com/)
* [Vultr](http://www.vultr.com/?ref=7110116-3B)
Please let us know if any of them requires tweaks or adjustments.
# Installing
## Create server
Create an `Ubuntu 16.04 (Xenial)` server with at-least `1gb` RAM and 20GB disk space.
Do not make any changes to vanilla ubuntu. Be sure to allocate a static IPv4 address
for your server.
Cloudron has a built-in firewall and ports are opened and closed dynamically, as and when
apps are installed, re-configured or removed. For this reason, be sure to open all TCP and
UDP traffic to the server and leave the traffic management to the Cloudron.
### Kimsufi
Be sure to check the "use the distribution kernel" checkbox in the personalized installation mode.
### Linode
Since Linode does not manage SSH keys, be sure to add the public key to
`/root/.ssh/authorized_keys`.
## Run setup
SSH into your server and run the following commands:
```
wget https://cloudron.io/cloudron-setup
chmod +x cloudron-setup
./cloudron-setup --provider <azure|digitalocean|ec2|lightsail|linode|ovh|rosehosting|scaleway|vultr|generic>
```
The setup will take around 10-15 minutes.
**cloudron-setup** takes the following arguments:
* `--provider` is the name of your VPS provider. If the name is not on the list, simply
choose `generic`. In most cases, the `generic` provider mostly will work fine.
If the Cloudron does not complete initialization, it may mean that
we have to add some vendor specific quirks. Please open a
[bug report](https://git.cloudron.io/cloudron/box/issues) in that case.
Optional arguments for installation:
* `--tls-provider` is the name of the SSL/TLS certificate backend. Defaults to Let's encrypt.
Specifying `fallback` will setup the Cloudron to use the fallback wildcard certificate.
Initially a self-signed one is provided, which can be overwritten later in the admin interface.
This may be useful for non-public installations.
* `--data-dir` is the path where Cloudron will store platform and application data. Note: data
directory must be an `ext4` filesystem.
Optional arguments used for update and restore:
* `--version` is the version of Cloudron to install. By default, the setup script installs
the latest version. You can set this to an older version when restoring a Cloudron from a backup.
* `--restore-url` is a backup URL to restore from.
## Domain setup
Once the setup script completes, the server will reboot, then visit your server by its
IP address (`https://ip`) to complete the installation.
The setup website will show a certificate warning. Accept the self-signed certificate
and proceed to the domain setup.
Currently, only subdomains of the [Public Suffix List](https://publicsuffix.org/) are supported.
For example, `example.com`, `example.co.uk` will work fine. Choosing other non-registrable
domain names like `cloudron.example.com` will not work.
### Route 53
Create root or IAM credentials and choose `Route 53` as the DNS provider.
* For root credentials:
* In AWS Console, under your name in the menu bar, click `Security Credentials`
* Click on `Access Keys` and create a key pair.
* For IAM credentials:
* You can use the following policy to create IAM credentials:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "route53:*",
"Resource": [
"arn:aws:route53:::hostedzone/<hosted zone id>"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
"route53:GetChange"
],
"Resource": [
"*"
]
}
]
}
```
### Digital Ocean
Create an API token with read+write access and choose `Digital Ocean` as the DNS provider.
### Other
If your domain *does not* use Route 53 or Digital Ocean, setup a wildcard (`*`) DNS `A` record that points to the
IP of the server created above. If your DNS provider has an API, please open an
[issue](https://git.cloudron.io/cloudron/box/issues) and we may be able to support it.
## Finish Setup
Once the domain setup is done, the Cloudron will configure the DNS and get a SSL certificate. It will automatically redirect to `https://my.<domain>`.
# Backups
The Cloudron creates encrypted backups once a day. Each app is backed up independently and these
backups have the prefix `app_`. The platform state is backed up independently with the
prefix `box_`.
By default, backups reside in `/var/backups`. Please note that having backups reside in the same
physical machine as the Cloudron server instance is dangerous and it must be changed to
an external storage location like `S3` as soon as possible.
## Amazon S3
Provide S3 backup credentials in the `Settings` page and leave the endpoint field empty.
Create a bucket in S3 (You have to have an account at [AWS](https://aws.amazon.com/)). The bucket can be setup to periodically delete old backups by
adding a lifecycle rule using the AWS console. S3 supports both permanent deletion
or moving objects to the cheaper Glacier storage class based on an age attribute.
With the current daily backup schedule a setting of two days should be sufficient
for most use-cases.
* For root credentials:
* In AWS Console, under your name in the menu bar, click `Security Credentials`
* Click on `Access Keys` and create a key pair.
* For IAM credentials:
* You can use the following policy to create IAM credentials:
```
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<your bucket name>",
"arn:aws:s3:::<your bucket name>/*"
]
}
]
}
```
The `Encryption key` is an arbitrary passphrase used to encrypt the backups. Keep the passphrase safe; it is
required to decrypt the backups when restoring the Cloudron.
## Minio S3
[Minio](https://minio.io/) is a distributed object storage server, providing the same API as Amazon S3.
Since Cloudron supports S3, any API compatible solution should be supported as well, if this is not the case, let us know.
Minio can be setup, by following the [installation instructions](https://docs.minio.io/) on any server, which is reachable by the Cloudron.
Do not setup Minio on the same server as the Cloudron, this will inevitably result in data loss, if backups are stored on the same instance.
Once setup, minio will print the necessary information, like login credentials, region and endpoints in its logs.
```
$ ./minio server ./storage
Endpoint: http://192.168.10.113:9000 http://127.0.0.1:9000
AccessKey: GFAWYNJEY7PUSLTHYHT6
SecretKey: /fEWk66E7GsPnzE1gohqKDovaytLcxhr0tNWnv3U
Region: us-east-1
```
First create a new bucket for the backups, using the minio commandline tools or the webinterface. The bucket has to have **read and write** permissions.
The information to be copied to the Cloudron's backup settings form may look similar to:
<img src="/docs/img/minio_backup_config.png" class="shadow"><br/>
The `Encryption key` is an arbitrary passphrase used to encrypt the backups. Keep the passphrase safe; it is
required to decrypt the backups when restoring the Cloudron.
# Email
Cloudron has a built-in email server. By default, it only sends out email on behalf of apps
(for example, password reset or notification). You can enable the email server for sending
and receiving mail on the `settings` page. This feature is only available if you have setup
a DNS provider like Digital Ocean or Route53.
Your server's IP plays a big role in how emails from our Cloudron get handled. Spammers
frequently abuse public IP addresses and as a result your Cloudron might possibly start
out with a bad reputation. The good news is that most IP based blacklisting services cool
down over time. The Cloudron sets up DNS entries for SPF, DKIM, DMARC automatically and
reputation should be easy to get back.
## Checklist
* If you are unable to receive mail, first thing to check is if your VPS provider lets you
receive mail on port 25.
* Digital Ocean - New accounts frequently have port 25 blocked. Write to their support to
unblock your server.
* EC2, Lightsail & Scaleway - Edit your security group to allow email.
* Setup a Reverse DNS PTR record to be setup for the `my` subdomain.
**Note:** PTR records are a feature of your VPS provider and not your domain provider.
* You can verify the PTR record [https://mxtoolbox.com/ReverseLookup.aspx](here).
* AWS EC2 & Lightsail - Fill the [PTR request form](https://aws-portal.amazon.com/gp/aws/html-forms-controller/contactus/ec2-email-limit-rdns-request).
* Digital Ocean - Digital Ocean sets up a PTR record based on the droplet's name. So, simply rename
your droplet to `my.<domain>`. Note that some new Digital Ocean accounts have [port 25 blocked](https://www.digitalocean.com/community/questions/port-25-smtp-external-access).
* Linode - Follow this [guide](https://www.linode.com/docs/networking/dns/setting-reverse-dns).
* Scaleway - Edit your security group to allow email and [reboot the server](https://community.online.net/t/security-group-not-working/2096) for the change to take effect. You can also set a PTR record on the interface with your `my.<domain>`.
* Check if your IP is listed in any DNSBL list [here](http://multirbl.valli.org/) and [here](http://www.blk.mx).
In most cases, you can apply for removal of your IP by filling out a form at the DNSBL manager site.
* When using wildcard or manual DNS backends, you have to setup the DMARC, MX records manually.
* Finally, check your spam score at [mail-tester.com](https://www.mail-tester.com/). The Cloudron
should get 100%, if not please let us know.
# CLI Tool
The [Cloudron tool](https://git.cloudron.io/cloudron/cloudron-cli) is useful for managing
a Cloudron. <b class="text-danger">The Cloudron CLI tool has to be installed & run on a Laptop or PC</b>
Once installed, you can install, configure, list, backup and restore apps from the command line.
## Linux & OS X
Installing the CLI tool requires node.js and npm. The CLI tool can be installed using the following command:
```
npm install -g cloudron
```
Depending on your setup, you may need to run this as root.
On OS X, it is known to work with the `openssl` package from homebrew.
See [#14](https://git.cloudron.io/cloudron/cloudron-cli/issues/14) for more information.
## Windows
The CLI tool does not work on Windows. Please contact us on our [chat](https://chat.cloudron.io) if you want to help with Windows support.
# Updates
Apps installed from the Cloudron Store are automatically updated every night.
The Cloudron platform itself updates in two ways: update or upgrade.
### Update
An **update** is applied onto the running server instance. Such updates are performed
every night. You can also use the Cloudron UI to initiate an update immediately.
The Cloudron will always make a complete backup before attempting an update. In the unlikely
case an update fails, it can be [restored](/references/selfhosting.html#restore).
### Upgrade
An **upgrade** requires a new OS image. This process involves creating a new server from scratch
with the latest code and restoring it from the last backup.
To upgrade follow these steps closely:
* Create a new backup - `cloudron machine backup create`
* List the latest backup - `cloudron machine backup list`
* Make the backup available for the new cloudron instance:
* `S3` - When storing backup ins S3, make the latest box backup public - files starting with `box_` (from v0.94.0) or `backup_`. This can be done from the AWS S3 console as seen here:
<img src="/docs/img/aws_backup_public.png" class="shadow haze"><br/>
Copy the new public URL of the latest backup for use as the `--restore-url` below.
<img src="/docs/img/aws_backup_link.png" class="shadow haze"><br/>
* `File system` - When storing backups in `/var/backups`, you have to make the box and the app backups available to the new Cloudron instance's `/var/backups`. This can be achieved in a variety of ways depending on the situation: like scp'ing the backup files to the machine before installation, mounting the external backup hard drive into the new Cloudron's `/var/backup` OR downloading a copy of the backup using `cloudron machine backup download` and uploading them to the new machine. After doing so, pass `file:///var/backups/<path to box backup>` as the `--restore-url` below.
* Create a new Cloudron by following the [installing](/references/selfhosting.html#installing) section.
When running the setup script, pass in the `--encryption-key` and `--restore-url` flags.
The `--encryption-key` is the backup encryption key. It can be displayed with `cloudron machine info`
Similar to the initial installation, a Cloudron upgrade looks like:
```
$ ssh root@newserverip
> wget https://cloudron.io/cloudron-setup
> chmod +x cloudron-setup
> ./cloudron-setup --provider <digitalocean|ec2|generic|scaleway> --domain <example.com> --encryption-key <key> --restore-url <publicS3Url>
```
Note: When upgrading an old version of Cloudron (<= 0.94.0), pass the `--version 0.94.1` flag and then continue updating
from that.
* Finally, once you see the newest version being displayed in your Cloudron webinterface, you can safely delete the old server instance.
# Restore
To restore a Cloudron from a specific backup:
* Select the backup - `cloudron machine backup list`
* Make the backup public
* `S3` - Make the box backup publicly readable - files starting with `box_` (from v0.94.0) or `backup_`. This can be done from the AWS S3 console. Once the box has restored, you can make it private again.
* `File system` - When storing backups in `/var/backups`, you have to make the box and the app backups available to the new Cloudron instance's `/var/backups`. This can be achieved in a variety of ways depending on the situation: like scp'ing the backup files to the new machine before Cloudron installation OR mounting an external backup hard drive into the new Cloudron's `/var/backup` OR downloading a copy of the backup using `cloudron machine backup download` and uploading them to the new machine. After doing so, pass `file:///var/backups/<path to box backup>` as the `--restore-url` below.
* Create a new Cloudron by following the [installing](/references/selfhosting.html#installing) section.
When running the setup script, pass in the `version`, `encryption-key`, `domain` and `restore-url` flags.
The `version` field is the version of the Cloudron that the backup corresponds to (it is embedded
in the backup file name).
* Make the box backup private, once the upgrade is complete.
# Security
Security is a core feature of the Cloudron and we continue to push out updates to tighten the Cloudron's security policy. Our goal is that Cloudron users should be able to rely on Cloudron being secure out of the box without having to do manual configuration.
This section lists various security measures in place to protect the Cloudron.
## HTTP Security
* Cloudron admin has a CSP policy that prevents XSS attacks.
* Cloudron set various security related HTTP headers like `X-XSS-Protection`, `X-Download-Options`,
`X-Content-Type-Options`, `X-Permitted-Cross-Domain-Policies`, `X-Frame-Options` across all apps.
## SSL
* Cloudron enforces HTTPS across all apps. HTTP requests are automatically redirected to
HTTPS.
* The Cloudron automatically installs and renews certificates for your apps as needed. Should
installation of certificate fail for reasons beyond it's control, Cloudron admins will get a notification about it.
* Cloudron sets the `Strict-Transport-Security` header (HSTS) to protect apps against downgrade attacks
and cookie hijacking.
* Cloudron has A+ rating for SSL from [SSL Labs](https://cloudron.io/blog/2017-02-22-release-0.102.0.html).
## App isolation
* Apps are isolated completely from one another. One app cannot tamper with another apps' database or
local files. We achieve this using Linux Containers.
* Apps run with a read-only rootfs preventing attacks where the application code can be tampered with.
* Apps can only connect to addons like databases, LDAP, email relay using authentication.
* Apps are run with an AppArmor profile that disables many system calls and restricts access to `proc`
and `sys` filesystems.
* Most apps are run as non-root user. In the future, we intend to implement user namespaces.
* Each app is run in it's own subdomain as opposed to sub-paths. This ensures that XSS vulnerabilities
in one app doesn't [compromise](https://security.stackexchange.com/questions/24155/preventing-insecure-webapp-on-subdomain-compromise-security-of-main-webapp) other apps.
## Email
* Cloudron checks against the [Zen Spamhaus DNSBL](https://www.spamhaus.org/zen/) before accepting mail.
* Email can only be accessed with IMAP over TLS (IMAPS).
* Email can only be relayed (including same-domain emails) by authenticated users using SMTP/STARTTLS.
* Cloudron ensures that `MAIL FROM` is the same as the authenticated user. Users cannot spoof each other.
* All outbound mails from Cloudron are `DKIM` signed.
* Cloudron automatically sets up SPF, DMARC policies in the DNS for best email delivery.
* All incoming mail is scanned via `Spamassasin`.
## Firewall
* Cloudron blocks all incoming ports except 22 (ssh), 80 (http), 443 (https)
* When email is enabled, Cloudron allows 25 (SMTP), 587 (MSA), 993 (IMAPS) and 4190 (WebSieve)
## OS Updates
* Ubuntu [automatic security updates](https://help.ubuntu.com/community/AutomaticSecurityUpdates) are enabled
## Rate limits
The goal of rate limits is to prevent password brute force attacks.
* Cloudron password verification routes - 10 requests per second per IP.
* HTTP and HTTPS requests - 5000 requests per second per IP.
* SSH access - 5 connections per 10 seconds per IP.
* Email access (Port 25, 587, 993, 4190) - 50 connections per second per IP/App.
* Database addons access - 5000 connections per second per app (addons use 128 byte passwords).
* Email relay access - 500 connections per second per app.
* Email receive access - 50 connections per second per app.
* Auth addon access - 500 connections per second per app.
## Password restrictions
* Cloudron requires user passwords to have 1 uppercase, 1 number and 1 symbol.
* Minimum length for user passwords is 8
## Privacy
* Cloudron apps have a default `Referrer-Policy` of `no-referrer-when-downgrade`.
* Backups are optionally encrypted with AES-256-CBC.
* Let's Encrypt [submits](https://letsencrypt.org/certificates/)
all certificates to [Certificate Transparency Logs](https://www.certificate-transparency.org/).
This means that the apps that you install and use are going to be guessable. For example,
[crt.sh](https://crt.sh) can display all your subdomains and you can visit those subdomains and
guess the app. Generally, this is not a problem because using hidden DNS names is not a security
measure. If you want to avoid this, you can always use a wildcard certificate.
* Cloudron does not collect any user information and this is not our business model. We collect
information regarding the configured backend types. This helps us focus on improving backends
based on their use. You can review the specific code [here](https://git.cloudron.io/cloudron/box/blob/master/src/appstore.js#L124).
# Data directory
If you are installing a brand new Cloudron, you can configure the data directory
that Cloudron uses by passing the `--data-dir` option to `cloudron-setup`.
Note: data directory must be an `ext4` filesystem.
```
./cloudron-setup --provider <digitalocean|ec2|generic|scaleway> --data-dir /var/cloudrondata
```
If you have an existing Cloudron, we recommend moving the existing data directory
to a new location as follows (`DATA_DIR` is the location to move your data):
```
systemctl stop cloudron.target
systemctl stop docker
DATA_DIR="/var/data"
mkdir -p "${DATA_DIR}"
mv /home/yellowtent/appsdata "${DATA_DIR}"
ln -s "${DATA_DIR}/appsdata" /home/yellowtent/appsdata
mv /home/yellowtent/platformdata "${DATA_DIR}"
ln -s "${DATA_DIR}/platformdata" /home/yellowtent/platformdata
systemctl start docker
systemctl start cloudron.target
```
# Debug
You can SSH into your Cloudron and collect logs:
* `journalctl -a -u box` to get debug output of box related code.
* `docker ps` will give you the list of containers. The addon containers are named as `mail`, `postgresql`,
`mysql` etc. If you want to get a specific container's log output, `journalctl -a CONTAINER_ID=<container_id>`.
# Alerts
The Cloudron will notify the Cloudron administrator via email if apps go down, run out of memory, have updates
available etc.
You will have to setup a 3rd party service like [Cloud Watch](https://aws.amazon.com/cloudwatch/) or [UptimeRobot](http://uptimerobot.com/) to monitor the Cloudron itself. You can use `https://my.<domain>/api/v1/cloudron/status`
as the health check URL.
# Help
If you run into any problems, join us at our [chat](https://chat.cloudron.io) or [email us](mailto:support@cloudron.io).

View File

@@ -1,366 +0,0 @@
# Introduction
The Cloudron is the best platform self-hosting web applications on your server. You
can easily install apps on it, add users, manage access restriction and keep your
server and apps updated with no effort.
You might wonder that there are so many 1-click app solutions out there and what is so special
about Cloudron? As the name implies, 1-click installers simply install code into a server
and leave it at that. There's so much more to do:
1. Configure a domain to point to your server
2. Setup SSL certificates and renew them periodically
3. Ensure apps are backed up correctly
4. Ensure apps are uptodate and secure
5. Have a mechanism to quickly restore apps from a backup
6. Manage users across all your apps
7. Get alerts and notifications about the status of apps
... and so on ...
We made the Cloudron to dramatically lower the bar for people to run apps on servers. Just provide
a domain name, install apps and add users. All the server management tasks listed above is
completely automated.
If you want to learn more about the secret sauce that makes the Cloudron, please read our
[architecture overview](/references/architecture.html).
# Use cases
Here are some of the apps you can run on a Cloudron:
* RSS Reader
* Chat, IRC, Jabber servers
* Public forum
* Blog
* File syncing and sharing
* Code hosting
* Email
Our list of apps is growing everyday, so be sure to [follow us on twitter](https://twitter.com/cloudron_io).
# Activation
When you first create the Cloudron, the setup wizard will ask you to setup an administrator
account. Don't worry, a Cloudron adminstrator doesn't need to know anything about maintaining
a server! It's the whole reason why we made the Cloudron. Being a Cloudron administrator is
more analagous to being the owner of a smartphone. You can always add more administrators to
the Cloudron from the `Users` menu item.
<img src="/docs/img/webadmin_domain.png" class="shadow">
The Cloudron administration page is located at the `my` subdomain. You might want to bookmark
this link!
# Apps
## Installation
You can install apps on the Cloudron by choosing the `App Store` menu item. Use the 'Search' bar
to search for apps.
Clicking on app gives you information about the app.
<img src="/docs/img/app_info.png" class="shadow">
Clicking the `Install` button will show an install dialog like below:
<img src="/docs/img/app_install.png" class="shadow">
The `Location` field is the subdomain in which your app will be installed. For example, if you use the
`mail` location for your web mail client, then it will be accessible at `mail.<domain>`.
Tip: You can access the apps directly on your browser using `mail.<domain>`. You don't have to
visit the Cloudron administration panel.
`Access control` specifies who can access this app.
* `Every Cloudron user` - Any user in your Cloudron can access the app. Initially, you are the only
user in your Cloudron. Unless you explicitly invite others, nobody else can access these apps.
Note that the term 'access' depends on the app. For a blog, this means that nobody can post new
blog posts (but anybody can view them). For a chat server, this might mean that nobody can access
your chat server.
* `Restrict to groups` - Only users in the groups can access the app.
## Updates
All your apps automatically update as and when the application author releases an update. The Cloudron
will attempt to update around midnight of your timezone.
Some app updates are not automatic. This can happen if a new version of the app has removed some features
that you were relying on. In such a case, the update has to be manually approved. This is simply a matter
of clicking the `Update` button (the green star) after you read about the changes.
<img src="/docs/img/app_update.png" class="shadow">
## Backups
<i>If you self-host, please refer to the [self-hosting documentation](/references/selfhosting.html#backups) for backups.</i>
All apps are automatically backed up every day. Backups are stored encrypted in Amazon S3. You don't have
to do anything about it. The [Cloudron CLI](https://git.cloudron.io/cloudron/cloudron-cli) tool can be used
to download application backups.
## Configuration
Apps can be reconfigured using the `Configure` button.
<img src="/docs/img/app_configure_button.png" class="shadow">
Click on the wrench button will bring up the configure dialog.
<img src="/docs/img/app_configure.png" class="shadow">
You can do the following:
* Change the location to move the app to another subdomain. Say, you want to move your blog from `blog` to `about`.
* Change who can access the app.
Changing an app's configuration has a small downtime (usually around a minute).
## Restore
Apps can be restored to a previous backup by clicking on the `Restore` button.
<img src="/docs/img/app_restore_button.png" class="shadow">
Note that restoring previous data might also restore the previous version of the software. For example, you might
be currently using Version 5 of the app. If you restore to a backup that was made with Version 3 of the app, then the restore
operation will install Version 3 of the app. This is because the latest version may not be able to handle old data.
## Uninstall
You can uninstall an app by clicking the `Uninstall` button.
<img src="/docs/img/app_uninstall_button.png" class="shadow">
Note that all data associated with the app will be immediately removed from the Cloudron. App data might still
persist in your old backups and the [CLI tool](https://git.cloudron.io/cloudron/cloudron-cli) provides a way to
restore from those old backups should it be required.
## Embedding Apps
It is possible to embed Cloudron apps into other websites. By default, this is disabled to prevent
[Clickjacking](https://cloudron.io/blog/2016-07-15-site-embedding.html).
You can set a website that is allowed to embed your Cloudron app using the app's [Configure dialog](#configuration).
Click on 'Show Advanced Settings...' and enter the embedder website name.
# Custom domain
When you create a Cloudron from cloudron.io, we provide a subdomain under `cloudron.me` like `girish.cloudron.me`.
Apps are available under that subdomain using a hyphenated name like `blog-girish.cloudron.me`.
Domain names are a thing of pride and the Cloudron makes it easy to make your apps accessible from memorable locations like `blog.girish.in`.
## Single app on a custom domain
This approach is applicable if you desire that only a single app be accessing from a custom
domain. For this, open the app's configure dialog and choose `External Domain` in the location dropdown.
<img src="/docs/img/app_external_domain.png" class="shadow">
This dialog will suggest you to add a `CNAME` record (for subdomains) or an `A` record (for naked domains).
Once you setup a record with your DNS provider, the app will be accessible from that external domain.
## Entire Cloudron on a custom domain
This approach is applicable if you want all your apps to be accessible from subdomains of your custom domain.
For example, `blog.girish.in`, `notes.girish.in`, `owncloud.girish.in`, `mail.girish.in` and so on. This
approach is also the only way that the Cloudron supports for sending and receiving emails from your domain.
For this, go to the 'Domains & Certs' menu item.
<img src="/docs/img/custom_domain_menu.png" class="shadow">
Change the domain name to your custom domain. Currently, we require that your domain be hosted on AWS Route53.
<img src="/docs/img/custom_domain_change.png" class="shadow">
Moving to a custom domain will retain all your apps and data and will take around 15 minutes. If you require assistance with another provider,
<a href="mailto:support@cloudron.io">just let us know</a>.
# User management
## Users
You can invite new users (friends, family, colleagues) with their email address from the `Users` menu. They will
receive an invite to sign up with your Cloudron. They can now access the apps that you have given them access
to.
<img src="/docs/img/users.png" class="shadow">
To remove a user, simply remove them from the list. Note that the removed user cannot access any app anymore.
## Administrators
A Cloudron administrator is a special right given to an existing Cloudron user allowing them to manage
apps and users. To make an existing user an administator, click the edit (pencil) button corresponding to
the user and check the `Allow this user to manage apps, groups and other users` checkbox.
<img src="/docs/img/administrator.png" class="shadow">
## Groups
Groups provide a convenient way to group users. It's purpose is two-fold:
* You can assign one or more groups to apps to restrict who can access for an app.
* Each group is a mailing list (forwarding address) constituting of it's members.
You can create a group by using the `Groups` menu item.
<img src="/docs/img/groups.png" class="shadow">
To set the access restriction use the app's configure dialog.
<img src="/docs/img/app_access_control.png" class="shadow">
You can now send mails to `groupname@<domain>` to address all the group members.
# Login
## Cloudron admin
The Cloudron admin page is always located at the `my` subdomain of your Cloudron domain. For custom domains,
this will be like `my.girish.in`. For domains from cloudron.io, this will be like `my-girish.cloudron.me`.
## Apps (single sign-on)
An important feature of the Cloudron is Single Sign-On. You use the same username & password for logging in
to all your apps. No more having to manage separate set of credentials for each service!
## Single user apps
Some apps only work with a single user. For example, a notes app might allow only a single user to login and add
notes. For such apps, you will be prompted during installation to select the single user who can access the app.
<img src="/docs/img/app_single_user.png" class="shadow">
If you want multiple users to use the app independently, simply install the app multiple times to different locations.
# Email
The Cloudron has a built-in email server. The primary email address is the same as the username. Emails can be sent
and received from `<username>@<domain>`. The Cloudron does not allow masquerading - one user cannot send email
pretending to be another user.
## Enabling Email
By default, Cloudron's email server only allows apps to send email. To enable users to send and receive email,
turn on the option under `Settings`. Turning on this option also allows apps to _receive_ email.
Once email is enabled, the Cloudron will keep the the `MX` DNS record updated.
<img src="/docs/img/enable_email.png" class="shadow">
## Receiving email using IMAP
Use the following settings to receive email.
* Server Name - Use the `my` subdomain of your Cloudron
* Port - 993
* Connection Security - TLS
* Username/password - Same as your Cloudron credentials
## Sending email using SMTP
Use the following settings to send email.
* Server Name - Use the `my` subdomain of your Cloudron
* Port - 587
* Connection Security - STARTTLS
* Username/password - Same as your Cloudron credentials
## Email filters using Sieve
Use the following settings to setup email filtering users via Manage Sieve.
* Server Name - Use the `my` subdomain of your Cloudron
* Port - 4190
* Connection Security - TLS
* Username/password - Same as your Cloudron credentials
The [Rainloop](https://cloudron.io/appstore.html?app=net.rainloop.cloudronapp) and [Roundcube](https://cloudron.io/appstore.html?app=net.roundcube.cloudronapp)
apps are already pre-configured to use the above settings.
## Aliases
You can configure one or more aliases alongside the primary email address of each user. You can set aliases by editing the
user's settings, available behind the edit button in the user listing. Note that aliases cannot conflict with existing user names.
<img src="/docs/img/email_alias.png" class="shadow">
Currently, it is not possible to login using the alias for SMTP/IMAP/Sieve services. Instead, add the alias as an identity in
your mail client but login using the Cloudron credentials.
## Subaddresses
Emails addressed to `<username>+tag@<domain>` will be delivered to the `username` mailbox. You can use this feature to give out emails of the form
`username+kayak@<domain>`, `username+aws@<domain>` and so on and have them all delivered to your mailbox.
## Forwarding addresses
Each group on the Cloudron is also a forwarding address. Mails can be addressed to `group@<domain>` and the mail will
be sent to each user who is part of the group.
## Marking Spam
The spam detection agent on the Cloudron requires training to identify spam. To do this, simply move your junk mails
to a pre-created folder named `Spam`. Most mail clients have a Junk or Spam button which does this automatically.
# Graphs
The Graphs view shows an overview of the disk and memory usage on your Cloudron.
<img src="/docs/img/graphs.png" class="shadow">
The `Disk Usage` graph shows you how much disk space you have left. Note that the Cloudron will
send the Cloudron admins an email notification when the disk is ~90% full.
The `Apps` Memory graph shows the memory consumed by each installed app. You can click on each segment
on the graph to see the memory consumption over time in the chart below it.
The `System` Memory graph shows the overall memory consumption on the entire Cloudron. If you see
the Free memory < 50MB frequently, you should consider upgrading to a Cloudron with more memory.
# Activity log
The `Activity` view shows the activity on your Cloudron. It includes information about who is using
the apps on your Cloudron and also tracks configuration changes.
<img src="/docs/img/activity.png" class="shadow">
# API Access
All the operations listed in this manual like installing app, configuring users and groups, are
completely programmable with a [REST API](/references/api.html).
# Domains and SSL Certificates
All apps on the Cloudron can only be reached by `https`. The Cloudron automatically installs and
renews certificates for your apps as needed. Should installation of certificate fail for reasons
beyond it's control, Cloudron admins will get a notification about it.
# OAuth Provider
Cloudron is an OAuth 2.0 provider. To integrate Cloudron login into an external application, create
an OAuth application under `API Access`.
You can use the following OAuth URLs to add Cloudron in the external app:
```
authorizationURL: https://my.<domain>/api/v1/oauth/dialog/authorize
tokenURL: https://my.<domain>/api/v1/oauth/token
```
# Moving to a larger Cloudron
When using a Cloudron from cloudron.io, it is easy to migrate your apps and data to a bigger server.
In the `Settings` page, you can change the plan.
<insert picture>
# Command line tool
If you are a software developer or a sysadmin, the Cloudron comes with a CLI tool that can be
used to develop custom apps for the Cloudron. Read more about it [here](https://git.cloudron.io/cloudron/cloudron-cli).

View File

@@ -1,623 +0,0 @@
# Overview
This tutorial provides an introduction to developing applications
for the Cloudron using node.js.
# Installation
## Install CLI tool
The Cloudron CLI tool allows you to install, configure and test apps on your Cloudron.
Installing the CLI tool requires [node.js](https://nodejs.org/) and
[npm](https://www.npmjs.com/). You can then install the CLI tool using the following
command:
```
sudo npm install -g cloudron
```
Note: Depending on your setup, you can run the above command without `sudo`.
## Testing your installation
The `cloudron` command should now be available in your path.
Let's login to the Cloudron as follows:
```
$ cloudron login
Cloudron Hostname: craft.selfhost.io
Enter credentials for craft.selfhost.io:
Username: girish
Password:
Login successful.
```
## Your First Application
Creating an application for Cloudron can be summarized as follows:
1. Create a web application using any language/framework. This web application must run a HTTP server
and can optionally provide other services using custom protocols (like git, ssh, TCP etc).
2. Create a [Dockerfile](http://docs.docker.com/engine/reference/builder/) that specifies how to create
an application ```image```. An ```image``` is essentially a bundle of the application source code
and it's dependencies.
3. Create a [CloudronManifest.json](/references/manifest.html) file that provides essential information
about the app. This includes information required for the Cloudron Store like title, version, icon and
runtime requirements like `addons`.
## Simple Web application
To keep things simple, we will start by deploying a trivial node.js server running on port 8000.
Create a new project folder `tutorial/` and add a file named `tutorial/server.js` with the following content:
```javascript
var http = require("http");
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
server.listen(8000);
console.log("Server running at port 8000");
```
## Dockerfile
A Dockerfile contains commands to assemble an image.
Create a file named `tutorial/Dockerfile` with the following content:
```dockerfile
FROM cloudron/base:0.10.0
ADD server.js /app/code/server.js
CMD [ "/usr/local/node-6.9.5/bin/node", "/app/code/server.js" ]
```
The `FROM` command specifies that we want to start off with Cloudron's [base image](/references/baseimage.html).
All Cloudron apps **must** start from this base image.
The `ADD` command copies the source code of the app into the directory `/app/code`.
While this example only copies a single file, the ADD command can be used to copy directory trees as well.
See the [Dockerfile](https://docs.docker.com/reference/builder/#add) documentation for more details.
The `CMD` command specifies how to run the server. There are multiple versions of node available under `/usr/local`. We
choose node v6.9.5 for our app.
## CloudronManifest.json
The `CloudronManifest.json` specifies
* Information about displaying the app on the Cloudron Store. For example,
the title, author information, description etc
* Information for installing the app on the Cloudron. This includes fields
like httpPort, tcpPorts.
Create the CloudronManifest.json using the following command:
```
$ cloudron init
id: io.cloudron.tutorial # unique id for this app. use reverse domain name convention
author: John Doe # developer or company name of the for user <email>
title: Tutorial App # Cloudron Store title of this app
description: App that uses node.js # A string or local file reference like file://DESCRIPTION.md
tagline: Changing the world one app at a time # A tag line for this app for the Cloudron Store
website: https://cloudron.io # A link to this app's website
contactEmail: support@cloudron.io # Contact email of developer or company
httPort: 8000 # The http port on which this application listens to
```
The above command creates a CloudronManifest.json:
File ```tutorial/CloudronManifest.json```
```json
{
"id": "io.cloudron.tutorial",
"author": "John Doe",
"title": "Tutorial App",
"description": "App that uses node.js",
"tagline": "Changing the world one app at a time",
"version": "0.0.1",
"healthCheckPath": "/",
"httpPort": 8000,
"addons": {
"localstorage": {}
},
"minBoxVersion": "0.0.1",
"manifestVersion": 1,
"website": "https://cloudron.io",
"contactEmail": "support@cloudron.io",
"icon": "",
"mediaLinks": []
}
```
You can read in more detail about each field in the [Manifest reference](/references/manifest.html).
# Installing
## Building
We now have all the necessary files in place to build and deploy the app to the Cloudron.
Building creates an image of the app using the Dockerfile which can then be used to deploy
to the Cloudron.
Building, pushing and pulling docker images is very bandwidth and CPU intensive. To alleviate this
problem, apps are built using the `build service` which uses `cloudron.io` account credentials.
**Warning**: As of this writing, the build service uses the public Docker registry and the images that are built
can be downloaded by anyone. This means that your source code will be viewable by others.
Initiate a build using ```cloudron build```:
```
$ cloudron build
Building io.cloudron.tutorial@0.0.1
Appstore login:
Email: ramakrishnan.girish@gmail.com # cloudron.io account
Password: # Enter password
Login successful.
Build scheduled with id 76cebfdd-7822-4f3d-af17-b3eb393ae604
Downloading source
Building
Step 0 : FROM cloudron/base:0.10.0
---> 97583855cc0c
Step 1 : ADD server.js /app/code
---> b09b97ecdfbc
Removing intermediate container 03c1e1f77acb
Step 2 : CMD /usr/local/node-6.9.5/bin/node /app/code/main.js
---> Running in 370f59d87ab2
---> 53b51eabcb89
Removing intermediate container 370f59d87ab2
Successfully built 53b51eabcb89
The push refers to a repository [cloudron/img-2074d69134a7e0da3d6cdf3c53e241c4] (len: 1)
Sending image list
Pushing repository cloudron/img-2074d69134a7e0da3d6cdf3c53e241c4 (1 tags)
Image already pushed, skipping 57f52d167bbb
Image successfully pushed b09b97ecdfbc
Image successfully pushed 53b51eabcb89
Pushing tag for rev [53b51eabcb89] on {https://cdn-registry-1.docker.io/v1/repositories/cloudron/img-2074d69134a7e0da3d6cdf3c53e241c4/tags/76cebfdd-7822-4f3d-af17-b3eb393ae604}
Build succeeded
```
## Installing
Now that we have built the image, we can install our latest build on the Cloudron
using the following command:
```
$ cloudron install
Using cloudron craft.selfhost.io
Using build 76cebfdd-7822-4f3d-af17-b3eb393ae604 from 1 hour ago
Location: tutorial # This is the location into which the application installs
App is being installed with id: 4dedd3bb-4bae-41ef-9f32-7f938995f85e
=> Waiting to start installation
=> Registering subdomain .
=> Verifying manifest .
=> Downloading image ..............
=> Creating volume .
=> Creating container
=> Setting up collectd profile ................
=> Waiting for DNS propagation ...
App is installed.
```
This makes the app available at https://tutorial-craft.selfhost.io.
Open the app in your default browser:
```
cloudron open
```
You should see `Hello World`.
# Testing
The application testing cycle involves `cloudron build` and `cloudron install`.
Note that `cloudron install` updates an existing app in place.
You can view the logs using `cloudron logs`. When the app is running you can follow the logs
using `cloudron logs -f`.
For example, you can see the console.log output in our server.js with the command below:
```
$ cloudron logs
Using cloudron craft.selfhost.io
2015-05-08T03:28:40.233940616Z Server running at port 8000
```
It is also possible to run a *shell* and *execute* arbitrary commands in the context of the application
process by using `cloudron exec`. By default, exec simply drops you into an interactive bash shell with
which you can inspect the file system and the environment.
```
$ cloudron exec
```
You can also execute arbitrary commands:
```
$ cloudron exec env # display the env variables that your app is running with
```
# Storing data
For file system storage, an app can use the `localstorage` addon to store data under `/app/data`.
When the `localstorage` addon is active, any data under /app/data is automatically backed up. When an
app is updated, /app/data already contains the data generated by the previous version.
*Note*: For convenience, the initial CloudronManifest.json generated by `cloudron init` already contains this
addon.
Let us put this theory into action by saving a *visit counter* as a file.
*server.js* has been modified to count the number of visitors on the site by storing a counter
in a file named ```counter.dat```.
File ```tutorial/server.js```
```javascript
var http = require('http'),
fs = require('fs'),
util = require('util');
var COUNTER_FILE = '/app/data/counter.dat';
var server = http.createServer(function (request, response) {
var counter = 0;
if (fs.existsSync(COUNTER_FILE)) {
// read existing counter if it exists
counter = parseInt(fs.readFileSync(COUNTER_FILE, 'utf8'), 10);
}
response.writeHead(200, {"Content-Type": "text/plain"});
response.end(util.format("Hello World. %s visitors have visited this page\n", counter));
++counter; // bump the counter
fs.writeFileSync(COUNTER_FILE, counter + '', 'utf8'); // save back counter
});
server.listen(8000);
console.log("Server running at port 8000");
```
Now every time you refresh the page you will notice that the counter bumps up. You will
also notice that if you make changes to the app and do a `cloudron install`, the `counter.dat`
is *retained* across updates.
# Database
Most web applications require a database of some form. In theory, it is possible to run any
database you want as part of the application image. This is, however, a waste of server resources
should every app runs it's own database server.
To solve this, the Cloudron provides shareable resources like databases in form of ```addons```.
The database server is managed by the Cloudron and the application simply needs to request access to
the database in the CloudronManifest.json. While the database server itself is a shared resource, the
databases are exclusive to the application. Each database is password protected and accessible only
to the application. Databases and tables can be configured without restriction as the application
requires.
Cloudron currently provides `mysql`, `postgresql`, `mongodb`, `redis` database addons.
For this tutorial, let us try to save the counter in `redis` addon. For this, we make use of the
[redis](https://www.npmjs.com/package/redis) module.
Since this is a node.js app, let's add a very basic `package.json` containing the `redis` module dependency.
File `tutorial/package.json`
```json
{
"name": "tutorial",
"version": "1.0.0",
"dependencies": {
"redis": "^0.12.1"
}
}
```
and modify our Dockerfile to look like this:
File `tutorial/Dockerfile`
```dockerfile
FROM cloudron/base:0.10.0
ENV PATH /usr/local/node-6.9.5/bin:$PATH
ADD server.js /app/code/server.js
ADD package.json /app/code/package.json
WORKDIR /app/code
RUN npm install --production
CMD [ "node", "/app/code/server.js" ]
```
Notice the new `RUN` command which installs the node module dependencies in package.json using `npm install`.
Since we want to use redis, we have to modify the CloudronManifest.json to make redis available for this app.
File `tutorial/CloudronManifest.json`
```json
{
"id": "io.cloudron.tutorial",
"author": "John Doe",
"title": "Tutorial App",
"description": "App that uses node.js",
"tagline": "Changing the world one app at a time",
"version": "0.0.1",
"healthCheckPath": "/",
"httpPort": 8000,
"addons": {
"localstorage": {},
"redis": {}
},
"minBoxVersion": "0.0.1",
"manifestVersion": 1,
"website": "https://cloudron.io",
"contactEmail": "support@cloudron.io",
"icon": "",
"mediaLinks": []
}
```
When the application runs, environment variables `REDIS_HOST`, `REDIS_PORT` and
`REDIS_PASSWORD` are injected. You can read about the environment variables in the
[Redis reference](/references/addons.html#redis).
Let's change `server.js` to use redis instead of file backed counting:
File ```tutorial/server.js```
```javascript
var http = require('http'),
fs = require('fs'),
util = require('util'),
redis = require('redis');
var redisClient = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_HOST);
redisClient.auth(process.env.REDIS_PASSWORD);
redisClient.on("error", function (err) {
console.log("Redis Client Error " + err);
});
var COUNTER_KEY = 'counter';
var server = http.createServer(function (request, response) {
redisClient.get(COUNTER_KEY, function (err, reply) {
var counter = (!err && reply) ? parseInt(reply, 10) : 0;
response.writeHead(200, {"Content-Type": "text/plain"});
response.end(util.format("Hello World. %s visitors have visited this page\n", counter));
redisClient.incr(COUNTER_KEY);
});
});
server.listen(8000);
console.log("Server running at port 8000");
```
Simply `cloudron build` and `cloudron install` to test your app!
# Authentication
The Cloudron has a centralized panel for managing users and groups. Apps can integrate Single Sign-On
authentication using LDAP or OAuth.
Note that apps that are single user can skip Single Sign-On support. The Cloudron implements an `OAuth
proxy` (accessed through the app configuration dialog) that optionally lets the Cloudron admin make the
app visible only for logged in users.
## LDAP
Let's start out by adding the [ldap](/references/addons.html#ldap) addon to the manifest.
File `tutorial/CloudronManifest.json`
```json
{
"id": "io.cloudron.tutorial",
"author": "John Doe",
"title": "Tutorial App",
"description": "App that uses node.js",
"tagline": "Changing the world one app at a time",
"version": "0.0.1",
"healthCheckPath": "/",
"httpPort": 8000,
"addons": {
"localstorage": {},
"ldap": {}
},
"minBoxVersion": "0.0.1",
"manifestVersion": 1,
"website": "https://cloudron.io",
"contactEmail": "support@cloudron.io",
"icon": "",
"mediaLinks": []
}
```
Building and installing the app shows that the app gets new LDAP specific environment variables.
```
$ cloudron build
$ cloudron install
$ cloudron exec env | grep LDAP
LDAP_SERVER=172.17.42.1
LDAP_PORT=3002
LDAP_URL=ldap://172.17.42.1:3002
LDAP_USERS_BASE_DN=ou=users,dc=cloudron
LDAP_GROUPS_BASE_DN=ou=groups,dc=cloudron
```
Let's test the environment variables to use by using the [ldapjs](http://www.ldapjs.org) npm module.
We start by adding ldapjs to package.json.
File `tutorial/package.json`
```json
{
"name": "tutorial",
"version": "1.0.0",
"dependencies": {
"ldapjs": "^0.7.1"
}
}
```
The server code has been modified to authenticate using the `X-Username` and `X-Password` headers for
any path other than '/'.
File `tutorial/server.js`
```javascript
var http = require("http"),
ldap = require('ldapjs');
var ldapClient = ldap.createClient({ url: process.env.LDAP_URL });
var server = http.createServer(function (request, response) {
if (request.url === '/') {
response.writeHead(200, {"Content-Type": "text/plain"});
return response.end();
}
var username = request.headers['x-username'] || '';
var password = request.headers['x-password'] || '';
var ldapDn = 'cn=' + username + ',' + process.env.LDAP_USERS_BASE_DN;
ldapClient.bind(ldapDn, password, function (error) {
if (error) {
response.writeHead(401, {"Content-Type": "text/plain"});
response.end('Failed to authenticate: ' + error);
} else {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end('Successfully authenticated');
}
});
});
server.listen(8000);
console.log("Server running at port 8000");
```
Once we have used `cloudron build` and `cloudron install`, you can use `curl` to test
credentials as follows:
```bash
# Test with various credentials here. Your cloudon admin username and password should succeed.
curl -X 'X-Username: admin' -X 'X-Password: pass' https://tutorial-craft.selfhost.io/login
```
## OAuth
An app can integrate with OAuth 2.0 Authorization code grant flow by adding
[oauth](/references/addons.html#oauth) to CloudronManifest.json `addons` section.
Doing so will get the following environment variables:
```
$ cloudron exec env
OAUTH_CLIENT_ID=cid-addon-4089f65a-2adb-49d2-a6d1-e519b7d85e8d
OAUTH_CLIENT_SECRET=5af99a9633283aa15f5e6df4a108ff57f82064e4845de8bce8ad3af54dfa9dda
OAUTH_ORIGIN=https://my-craft.selfhost.io
API_ORIGIN=https://my-craft.selfhost.io
HOSTNAME=tutorial-craft.selfhost.io
```
OAuth Authorization code grant flow works as follows:
* App starts the flow by redirecting the user to Cloudron authorization endpoint of the following format:
```
https://API_ORIGIN/api/v1/oauth/dialog/authorize?response_type=code&client_id=OAUTH_CLIENT_ID&redirect_uri=CALLBACK_URL&scope=profile
```
In the above URL, API_ORIGIN and OAUTH_CLIENT_ID are environment variables. CALLBACK_URL is a url of the app
to which the user will be redirected back to after successful authentication. CALLBACK_URL has to have the
same origin as the app.
* The Cloudron OAuth server authenticates the user (using a password form) at the above URL. It also establishes
that the user grants the client's access request.
* If the user authenticated successfully, it will redirect the browser to CALLBACK_URL with a `code` query parameter.
* The app can exchange the `code` above for a `access token` by using the `OAUTH_CLIENT_SECRET`. It does so by making
a _POST_ request to the following url:
```
https://API_ORIGIN/api/v1/oauth/token?response_type=token&client_id=OAUTH_CLIENT_ID
```
with the following request body (json):
```json
{
"grant_type": "authorization_code",
"code": "<the code received in CALLBACK_URL query parameter>",
"redirect_uri": "https://<HOSTNAME>",
"client_id": "<OAUTH_CLIENT_ID>",
"client_secret": "<OAUTH_CLIENT_SECRET>"
}
```
In the above URL, API_ORIGIN, OAUTH_CLIENT_ID and HOSTNAME are environment variables. The response contains
the `access_token` in the body.
* The `access_token` can be used to get the [user's profile](/references/api.html#profile) using the following url:
```
https://API_ORIGIN/api/v1/profile?access_token=ACCESS_TOKEN
```
The `access_token` may also be provided in the `Authorization` header as `Bearer: <token>`.
An implementation of the above OAuth logic is at [ircd-app](https://github.com/cloudron-io/ircd-app/blob/master/settings/app.js).
The following libraries implement Cloudron OAuth for Ruby and Javascript.
* [omniauth-cloudron](https://github.com/cloudron-io/omniauth-cloudron)
* [passport-cloudron](https://github.com/cloudron-io/passport-cloudron)
# Beta Testing
Once your app is ready, you can upload it to the store for `beta testing` by
other Cloudron users. This can be done using:
```
cloudron appstore upload
```
The app should now be visible in the Store view of your cloudron under
the 'Testing' section. You can check if the icon, description and other details
appear correctly.
Other Cloudron users can install your app on their Cloudron's using
`cloudron install --appstore-id <appid@version>`. Note that this currently
requires your beta testers to install the CLI tool and put their Cloudron in
developer mode.
# Publishing
Once you are satisfied with the beta testing, you can submit it for review.
```
cloudron appstore submit
```
The cloudron.io team will review the app and publish the app to the store.
# Next steps
Congratulations! You are now well equipped to build web applications for the Cloudron.
# Samples
* [Lets Chat](https://github.com/cloudron-io/letschat-app)
* [Haste bin](https://github.com/cloudron-io/haste-app)
* [Pasteboard](https://github.com/cloudron-io/pasteboard-app)

View File

@@ -1,719 +0,0 @@
# Overview
This tutorial outlines how to package an existing web application for the Cloudron.
If you are aware of Docker and Heroku, you should feel at home packaging for the
Cloudron. Roughly, the steps involved are:
* Create a Dockerfile for your application. If your application already has a Dockerfile, it
is a good starting point for packaging for the Cloudron. By virtue of Docker, the Cloudron
is able to run apps written in any language/framework.
* Create a CloudronManifest.json that provides information like title, author, description
etc. You can also specify the addons (like database) required
to run your app. When the app runs on the Cloudron, it will have environment
variables set for connecting to the addon.
* Test the app on your Cloudron with the CLI tool.
* Optionally, submit the app to [Cloudron Store](/appstore.html).
# Prerequisites
## Install CLI tool
The Cloudron CLI tool allows you to install, configure and test apps on your Cloudron.
Installing the CLI tool requires [node.js](https://nodejs.org/) and
[npm](https://www.npmjs.com/). You can then install the CLI tool using the following
command:
```
sudo npm install -g cloudron
```
Note: Depending on your setup, you can run the above command without `sudo`.
## Login to Cloudron
The `cloudron` command should now be available in your path.
You can login to your Cloudron now:
```
$ cloudron login
Cloudron Hostname: craft.selfhost.io
Enter credentials for craft.selfhost.io:
Username: girish
Password:
Login successful.
```
# Basic app
We will first package a very simple app to understand how the packaging works.
You can clone this app from https://git.cloudron.io/cloudron/tutorial-basic.
## The server
The basic app server is a very simple HTTP server that runs on port 8000.
While the server in this tutorial uses node.js, you can write your server
in any language you want.
```server.js
var http = require("http");
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
server.listen(8000);
console.log("Server running at port 8000");
```
## Dockerfile
The Dockerfile contains instructions on how to create an image for your application.
```Dockerfile
FROM cloudron/base:0.10.0
ADD server.js /app/code/server.js
CMD [ "/usr/local/node-4.7.3/bin/node", "/app/code/server.js" ]
```
The `FROM` command specifies that we want to start off with Cloudron's [base image](/references/baseimage.html).
All Cloudron apps **must** start from this base image. This approach conserves space on the Cloudron since
Docker images tend to be quite large and also helps us to do a security audit on apps more easily.
The `ADD` command copies the source code of the app into the directory `/app/code`. There is nothing special
about the `/app/code` directory and it is merely a convention we use to store the application code.
The `CMD` command specifies how to run the server. The base image already contains many different versions of
node.js. We use Node 4.7.3 here.
This Dockerfile can be built and run locally as:
```
docker build -t tutorial .
docker run -p 8000:8000 -t tutorial
```
## Manifest
The `CloudronManifest.json` specifies
* Information for installing and running the app on the Cloudron. This includes fields like addons, httpPort, tcpPorts.
* Information about displaying the app on the Cloudron Store. For example, fields like title, author, description.
Create the CloudronManifest.json using `cloudron init` as follows:
```
$ cloudron init
id: io.cloudron.tutorial # unique id for this app. use reverse domain name convention
author: John Doe # developer or company name of the for user <email>
title: Tutorial App # Cloudron Store title of this app
description: App that uses node.js # A string or local file reference like file://DESCRIPTION.md
tagline: Changing the world one app at a time # A tag line for this app for the Cloudron Store
website: https://cloudron.io # A link to this app's website
contactEmail: support@cloudron.io # Contact email of developer or company
httPort: 8000 # The http port on which this application listens to
```
The above command creates a CloudronManifest.json:
File ```tutorial/CloudronManifest.json```
```json
{
"id": "io.cloudron.tutorial",
"title": "Tutorial App",
"author": "John Doe",
"description": "file://DESCRIPTION.md",
"changelog": "file://CHANGELOG",
"tagline": "Changing the world one app at a time",
"version": "0.0.1",
"healthCheckPath": "/",
"httpPort": 8000,
"addons": {
"localstorage": {}
},
"manifestVersion": 1,
"website": "https://cloudron.io",
"contactEmail": "support@cloudron.io",
"icon": "",
"tags": [
"changme"
],
"mediaLinks": [ ]
}
```
You can read in more detail about each field in the [Manifest reference](/references/manifest.html). The
`localstorage` addon allows the app to store files in `/app/data`. We will explore addons further further
down in this tutorial.
Additional files created by `init` are:
* `DESCRIPTION.md` - A markdown file providing description of the app for the Cloudron Store.
* `CHANGELOG` - A file containing change information for each version released to the Cloudron Store. This
information is shown when the user updates the app.
# Installing
We now have all the necessary files in place to build and deploy the app to the Cloudron.
## Building
Building, pushing and pulling docker images can be very bandwidth and CPU intensive. To alleviate this
problem, apps are built using the `build service` which uses `cloudron.io` account credentials.
**Warning**: As of this writing, the build service uses the public Docker registry and the images that are built
can be downloaded by anyone. This means that your source code will be viewable by others.
Initiate a build using ```cloudron build```:
```
$ cloudron build
Building io.cloudron.tutorial@0.0.1
cloudron.io login:
Email: ramakrishnan.girish@gmail.com # cloudron.io account
Password: # Enter password
Login successful.
Build scheduled with id e7706847-f2e3-4ba2-9638-3f334a9453a5
Waiting for build to begin, this may take a bit...
Downloading source
Building
Step 1 : FROM cloudron/base:0.10.0
---> be9fc6312b2d
Step 2 : ADD server.js /app/code/server.js
---> 10513e428d7a
Removing intermediate container 574573f6ed1c
Step 3 : CMD /usr/local/node-4.2.1/bin/node /app/code/server.js
---> Running in b541d149b6b9
---> 51aa796ea6e5
Removing intermediate container b541d149b6b9
Successfully built 51aa796ea6e5
Pushing
The push refers to a repository [docker.io/cloudron/img-062037096d69bbf3ffb5b9316ad89cb9] (len: 1)
Pushed 51aa796ea6e5
Pushed 10513e428d7a
Image already exists be9fc6312b2d
Image already exists a0261a2a7c75
Image already exists f9d4f0f1eeed
Image already exists 2b650158d5d8
e7706847-f2e3-4ba2-9638-3f334a9453a5: digest: sha256:8241d68b65874496191106ecf2ee8f3df2e05a953cd90ff074a6f8815a49389c size: 26098
Build succeeded
Success
```
## Installing
Now that we have built the image, we can install our latest build on the Cloudron
using the following command:
```
$ cloudron install
Using cloudron craft.selfhost.io
Using build 76cebfdd-7822-4f3d-af17-b3eb393ae604 from 1 hour ago
Location: tutorial # This is the location into which the application installs
App is being installed with id: 4dedd3bb-4bae-41ef-9f32-7f938995f85e
=> Waiting to start installation
=> Registering subdomain .
=> Verifying manifest .
=> Downloading image ..............
=> Creating volume .
=> Creating container
=> Setting up collectd profile ................
=> Waiting for DNS propagation ...
App is installed.
```
Open the app in your default browser:
```
cloudron open
```
You should see `Hello World`.
# Testing
The application testing cycle involves `cloudron build` and `cloudron install`.
Note that `cloudron install` updates an existing app in place.
You can view the logs using `cloudron logs`. When the app is running you can follow the logs
using `cloudron logs -f`.
For example, you can see the console.log output in our server.js with the command below:
```
$ cloudron logs
Using cloudron craft.selfhost.io
16:44:11 [main] Server running at port 8000
```
It is also possible to run a *shell* and *execute* arbitrary commands in the context of the application
process by using `cloudron exec`. By default, exec simply drops you into an interactive bash shell with
which you can inspect the file system and the environment.
```
$ cloudron exec
```
You can also execute arbitrary commands:
```
$ cloudron exec env # display the env variables that your app is running with
```
### Debugging
An app can be placed in `debug` mode by passing `--debug` to `cloudron install` or `cloudron configure`.
Doing so, runs the app in a non-readonly rootfs and unlimited memory. By default, this will also ignore
the `RUN` command specified in the Dockerfile. The developer can then interactively test the app and
startup scripts using `cloudron exec`.
This mode can be used to identify the files being modified by your application - often required to
debug situations where your app does not run on a readonly rootfs. Run your app using `cloudron exec`
and use `find / -mmin -30` to find file that have been changed or created in the last 30 minutes.
You can turn off debugging mode using `cloudron configure --no-debug`.
# Addons
## Filesystem
The application container created on the Cloudron has a `readonly` file system. Writing to any location
other than the below will result in an error:
* `/tmp` - Use this location for temporary files. The Cloudron will cleanup any files in this directory
periodically.
* `/run` - Use this location for runtime configuration and dynamic data. These files should not be expected
to persist across application restarts (for example, after an update or a crash).
* `/app/data` - Use this location to store application data that is to be backed up. To use this location,
you must use the [localstorage](/references/addons.html#localstorage) addon. For convenience, the initial CloudronManifest.json generated by
`cloudron init` already contains this addon.
## Database
Most web applications require a database of some form. In theory, it is possible to run any
database you want as part of the application image. This is, however, a waste of server resources
should every app runs it's own database server.
Cloudron currently provides [mysql](/references/addons.html#mysql), [postgresql](/references/addons.html#postgresql),
[mongodb](/references/addons.html#mongodb), [redis](/references/addons.html#redis) database addons. When choosing
these addons, the Cloudron will inject environment variables that contain information on how to connect
to the addon.
See https://git.cloudron.io/cloudron/tutorial-redis for a simple example of how redis can be used by
an application. The server simply uses the environment variables to connect to redis.
## Email
Cloudron applications can send email using the `sendmail` addon. Using the `sendmail` addon provides
the SMTP server and authentication credentials in environment variables.
Cloudron applications can also receive mail via IMAP using the `recvmail` addon.
## Authentication
The Cloudron has a centralized panel for managing users and groups. Apps can integrate Single Sign-On
authentication using LDAP or OAuth.
Apps can integrate with the Cloudron authentication system using LDAP, OAuth or Simple Auth. See the
[authentication](/references/authentication.html) reference page for more details.
See https://git.cloudron.io/cloudron/tutorial-ldap for a simple example of how to authenticate via LDAP.
For apps that are single user can skip Single Sign-On support by setting the `"singleUser": true`
in the manifest. By doing so, the Cloudron will installer will show a dialog to choose a user.
For app that have no user management at all, the Cloudron implements an `OAuth proxy` that
optionally lets the Cloudron admin make the app visible only for logged in users.
# Best practices
## No Setup
A Cloudron app is meant to instantly usable after installation. For this reason, Cloudron apps must not
show any setup screen after installation and should simply choose reasonable defaults.
Databases, email configuration should be automatically picked up from the environment variables using
addons.
## Docker
Cloudron uses Docker in the backend, so the package build script is a regular `Dockerfile`.
The app is run as a read-only docker container. Only `/run` (dynamic data), `/app/data` (backup data) and `/tmp` (temporary files) are writable at runtime. Because of this:
* Install any required packages in the Dockerfile.
* Create static configuration files in the Dockerfile.
* Create symlinks to dynamic configuration files under `/run` in the Dockerfile.
### Source directory
By convention, Cloudron apps install the source code in `/app/code`. Do not forget to create the directory for the code of the app:
```sh
RUN mkdir -p /app/code
WORKDIR /app/code
```
### Download archives
When packaging an app you often want to download and extract archives (e.g. from github).
This can be done in one line by combining `wget` and `tar` like this:
```docker
ENV VERSION 1.6.2
RUN wget "https://github.com/FreshRSS/FreshRSS/archive/${VERSION}.tar.gz" -O - \
| tar -xz -C /app/code --strip-components=1
```
The `--strip-components=1` causes the topmost directory in the archive to be skipped.
Always pin the download to a specific tag or commit instead of using `HEAD` or `master`
so that the builds are reasonably reproducible.
### Applying patches
To get the app working in Cloudron, sometimes it is necessary to patch the original sources. Patch is a safe way to modify sources, as it fails when the expected original sources changed too much.
First create a backup copy of the full sources (to be able to calculate the differences):
```sh
cp -a extensions extensions-orig
```
Then modify the sources in the original path and when finished, create a patch like this:
```sh
diff -Naru extensions-orig/ extensions/ > change-ttrss-file-path.patch
```
Add and apply this patch to the sources in the Dockerfile:
```docker
ADD change-ttrss-file-path.patch /app/code/change-ttrss-file-path.patch
RUN patch -p1 -d /app/code/extensions < /app/code/change-ttrss-file-path.patch
```
The `-p1` causes patch to ignore the topmost directory in the patch.
## Process manager
Docker supports restarting processes natively. Should your application crash, it will be restarted
automatically. If your application is a single process, you do not require any process manager.
Use supervisor, pm2 or any of the other process managers if you application has more then one component.
This **excludes** web servers like apache, nginx which can already manage their children by themselves.
Be sure to pick a process manager that [forwards signals](#sigterm-handling) to child processes.
## Automatic updates
Some apps support automatic updates by overwriting themselves. A Cloudron app cannot overwrite itself
because of the read-only file system. For this reason, disable auto updates for app and let updates be
triggered through the Cloudron Store. This ties in better to the Cloudron's update and restore approach
should something go wrong with the update.
## Logging
Cloudron applications stream their logs to stdout and stderr. In practice, this ideal is hard to achieve.
Some programs like apache simply don't log to stdout. In those cases, simply log to `/tmp` or `/run`.
Logging to stdout has many advantages:
* App does not need to rotate logs and the Cloudron takes care of managing logs.
* App does not need special mechanism to release log file handles (on a log rotate).
* Integrates better with tooling like cloudron cli.
## Memory
By default, applications get 256MB RAM (including swap). This can be changed using the `memoryLimit`
field in the manifest.
Design your application runtime for concurrent use by 50 users. The Cloudron is not designed for
concurrent access by 100s or 1000s of users.
An app can determine it's memory limit by reading `/sys/fs/cgroup/memory/memory.limit_in_bytes`.
## Authentication
Apps should integrate with one of the [authentication strategies](/references/authentication.html).
This saves the user from having to manage separate set of credentials for each app.
## Start script
Many apps do not launch the server directly, as we did in our basic example. Instead, they execute
a `start.sh` script (named so by convention) which is used as the app entry point.
At the end of the Dockerfile you should add your start script (`start.sh`) and set it as the default command.
Ensure that the `start.sh` is executable in the app package repo. This can be done with `chmod +x start.sh`.
```docker
ADD start.sh /app/code/start.sh
CMD [ "/app/code/start.sh" ]
```
### One-time init
One common pattern is to initialize the data directory with some commands once depending on the existence of a special `.initialized` file.
```sh
if ! [ -f /app/data/.initialized ]; then
echo "Fresh installation, setting up data directory..."
# Setup commands here
touch /app/data/.initialized
echo "Done."
fi
```
To copy over some files from the code directory you can use the following command:
```sh
rsync -a /app/code/config/ /app/data/config/
```
### chown data files
Since the app containers use other user ids than the host, it is sometimes necessary to change the permissions on the data directory:
```sh
chown -R cloudron.cloudron /app/data
```
For Apache+PHP apps you might need to change permissions to `www-data.www-data` instead.
### Persisting random values
Some apps need a random value that is initialized once and does not change afterwards (e.g. a salt for security purposes). This can be accomplished by creating a random value and storing it in a file in the data directory like this:
```sh
if ! [ -e /app/data/.salt ]; then
dd if=/dev/urandom bs=1 count=1024 2>/dev/null | sha1sum | awk '{ print $1 }' > /app/data/.salt
fi
SALT=$(cat /app/data/.salt)
```
### Generate config
Addon information (mail, database) exposed as environment are subject to change across restarts and an application must use these values directly (i.e not cache them across restarts). For this reason, it usually regenerates any config files with the current database settings on each invocation.
First create a config file template like this:
```sh
... snipped ...
'mysql' => array(
'driver' => 'mysql',
'host' => '##MYSQL_HOST',
'port' => '##MYSQL_PORT',
'database' => '##MYSQL_DATABASE',
'username' => '##MYSQL_USERNAME',
'password' => '##MYSQL_PASSWORD',
'charset' => 'utf8',
'collation' => 'utf8_general_ci',
'prefix' => '',
),
... snipped ...
```
Add the template file to the Dockerfile and create a symlink to the dynamic configuration file as follows:
```docker
ADD database.php.template /app/code/database.php.template
RUN ln -s /run/paperwork/database.php /app/code/database.php
```
Then in `start.sh`, generate the real config file under `/run` from the template like this:
```sh
sed -e "s/##MYSQL_HOST/${MYSQL_HOST}/" \
-e "s/##MYSQL_PORT/${MYSQL_PORT}/" \
-e "s/##MYSQL_DATABASE/${MYSQL_DATABASE}/" \
-e "s/##MYSQL_USERNAME/${MYSQL_USERNAME}/" \
-e "s/##MYSQL_PASSWORD/${MYSQL_PASSWORD}/" \
-e "s/##REDIS_HOST/${REDIS_HOST}/" \
-e "s/##REDIS_PORT/${REDIS_PORT}/" \
/app/code/database.php.template > /run/paperwork/database.php
```
### Non-root user
The cloudron runs the `start.sh` as root user. This is required for various commands like `chown` to
work as expected. However, to keep the app and cloudron secure, always run the app with the least
required permissions.
The `gosu` tool lets you run a binary with a specific user/group as follows:
```sh
/usr/local/bin/gosu cloudron:cloudron node /app/code/.build/bundle/main.js
```
### SIGTERM handling
bash, by default, does not automatically forward signals to child processes. This would mean that a SIGTERM sent to the parent processes does not reach the children. For this reason, be sure to `exec` as the
last line of the start.sh script. Programs like gosu, nginx, apache do proper SIGTERM handling.
For example, start apache using `exec` as below:
```sh
echo "Starting apache"
APACHE_CONFDIR="" source /etc/apache2/envvars
rm -f "${APACHE_PID_FILE}"
exec /usr/sbin/apache2 -DFOREGROUND
```
## Popular stacks
### Apache
Apache requires some configuration changes to work properly with Cloudron. The following commands configure Apache in the following way:
* Disable all default sites
* Print errors into the app's log and disable other logs
* Limit server processes to `5` (good default value)
* Change the port number to Cloudrons default `8000`
```docker
RUN rm /etc/apache2/sites-enabled/* \
&& sed -e 's,^ErrorLog.*,ErrorLog "/dev/stderr",' -i /etc/apache2/apache2.conf \
&& sed -e "s,MaxSpareServers[^:].*,MaxSpareServers 5," -i /etc/apache2/mods-available/mpm_prefork.conf \
&& a2disconf other-vhosts-access-log \
&& echo "Listen 8000" > /etc/apache2/ports.conf
```
Afterwards, add your site config to Apache:
```docker
ADD apache2.conf /etc/apache2/sites-available/app.conf
RUN a2ensite app
```
In `start.sh` Apache can be started using these commands:
```sh
echo "Starting apache..."
APACHE_CONFDIR="" source /etc/apache2/envvars
rm -f "${APACHE_PID_FILE}"
exec /usr/sbin/apache2 -DFOREGROUND
```
### PHP
PHP wants to store session data at `/var/lib/php/sessions` which is read-only in Cloudron. To fix this problem you can move this data to `/run/php/sessions` with these commands:
```docker
RUN rm -rf /var/lib/php/sessions && ln -s /run/php/sessions /var/lib/php/sessions
```
Don't forget to create this directory and it's ownership in the `start.sh`:
```sh
mkdir -p /run/php/sessions
chown www-data:www-data /run/php/sessions
```
### Java
Java scales its memory usage dynamically according to the available system memory. Due to how Docker works, Java sees the hosts total memory instead of the memory limit of the app. To restrict Java to the apps memory limit it is necessary to add a special parameter to Java calls.
```sh
LIMIT=$(($(cat /sys/fs/cgroup/memory/memory.memsw.limit_in_bytes)/2**20))
export JAVA_OPTS="-XX:MaxRAM=${LIMIT}M"
java ${JAVA_OPTS} -jar ...
```
# App Store
## Requirements
The Cloudron Store is a mechanism to share your app with others who use Cloudron. Currently, to ensure that
apps are maintained, secure and well supported there are some restrictions imposed on apps submitted to
the Cloudron Store. See [#292](https://git.cloudron.io/cloudron/box/issues/292) and [#327](https://git.cloudron.io/cloudron/box/issues/327) for an in-depth discussion.
The following criteria must be met before submitting an app for review:
* You must be willing to relocate your app packaging code to the [Cloudron Git Repo](https://git.cloudron.io/cloudron/).
* Contributed apps must have browser tests. You can see the various [app repos](https://git.cloudron.io/cloudron/) to get an idea on how to write these tests. The Cloudron team can help you write the tests.
* For all practical purposes, you are the maintainer of the app and Cloudron team will not commit to the repo
directly. Any changes will be submitted as Merge Requests.
* You agree that the Cloudron team can take over the responsibility of progressing the app further if you become unresponsive (48 hours), lose interest, lack time etc. Please send us an email if your priorities change.
* You must sign the [Cloudron CLA](https://cla.cloudron.io/).
As a token of our appreciation, 3rd party app authors can use the Cloudron for personal or business use for free.
## Upload for Testing
Once your app is ready, you can upload it to the store for `beta testing` by
other Cloudron users. This can be done using:
```
cloudron appstore upload
```
You should now be able to visit `/#/appstore/<appid>?version=<appversion>` on your
Cloudron to check if the icon, description and other details appear correctly.
Other Cloudron users can install your app on their Cloudron's using
`cloudron install --appstore-id <appid@version>`.
## Publishing
Once you are satisfied with the beta testing, you can submit it for review.
```
cloudron appstore submit
```
The cloudron.io team will review the app and publish the app to the store.
## Versioning and Updates
To create an update for an app, simply bump up the [semver version](/references/manifest.html#version) field in
the manifest and publish a new version to the store.
The Cloudron chooses the next app version to update to based on the following algorithm:
* Choose the maximum `patch` version matching the app's current `major` and `minor` version.
* Failing the above, choose the maximum patch version of the next minor version matching the app's current `major` version.
* Failing the above, choose the maximum patch and minor version of the next major version
For example, let's assume the versions 1.1.3, 1.1.4, 1.1.5, 1.2.4, 1.2.6, 1.3.0, 2.0.0 are published.
* If the app is running 1.1.3, then app will directly update to 1.1.5 (skipping 1.1.4)
* Once in 1.1.5, the app will update to 1.2.6 (skipping 1.2.4)
* Once in 1.2.6, the app will update to 1.3.0
* Once in 1.3.0, the app will update to 2.0.0
The Cloudron admins get notified by email for any major or minor app releases.
## Failed updates
The Cloudron always makes a backup of the app before making an update. Should the
update fail, the user can restore to the backup (which will also restore the app's
code to the previous version).
# Cloudron Button
The [Cloudron Button](/references/button.html) allows anyone to install your application with the click of a button
on their Cloudron.
The button can be added to just about any website including the application's website
and README.md files in GitHub repositories.
# Next steps
Congratulations! You are now well equipped to build web applications for the Cloudron.
You can see some examples of how real apps are packaged here:
* [Lets Chat](https://git.cloudron.io/cloudron/letschat-app)
* [Haste bin](https://git.cloudron.io/cloudron/haste-app)
* [Pasteboard](https://git.cloudron.io/cloudron/pasteboard-app)

View File

@@ -1,204 +0,0 @@
/* jslint node:true */
'use strict';
var argv = require('yargs').argv,
autoprefixer = require('gulp-autoprefixer'),
concat = require('gulp-concat'),
cssnano = require('gulp-cssnano'),
del = require('del'),
ejs = require('gulp-ejs'),
gulp = require('gulp'),
sass = require('gulp-sass'),
serve = require('gulp-serve'),
sourcemaps = require('gulp-sourcemaps'),
uglify = require('gulp-uglify'),
url = require('url');
gulp.task('3rdparty', function () {
gulp.src([
'webadmin/src/3rdparty/**/*.js',
'webadmin/src/3rdparty/**/*.map',
'webadmin/src/3rdparty/**/*.css',
'webadmin/src/3rdparty/**/*.otf',
'webadmin/src/3rdparty/**/*.eot',
'webadmin/src/3rdparty/**/*.svg',
'webadmin/src/3rdparty/**/*.gif',
'webadmin/src/3rdparty/**/*.ttf',
'webadmin/src/3rdparty/**/*.woff',
'webadmin/src/3rdparty/**/*.woff2'
])
.pipe(gulp.dest('webadmin/dist/3rdparty/'))
.pipe(gulp.dest('setup/splash/website/3rdparty'));
gulp.src('node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js')
.pipe(gulp.dest('webadmin/dist/3rdparty/js'))
.pipe(gulp.dest('setup/splash/website/3rdparty/js'));
});
// --------------
// JavaScript
// --------------
if (argv.help || argv.h) {
console.log('Supported arguments for "gulp develop":');
console.log(' --client-id <clientId>');
console.log(' --client-secret <clientSecret>');
console.log(' --api-origin <cloudron api uri>');
process.exit(1);
}
gulp.task('js', ['js-index', 'js-setup', 'js-setupdns', 'js-update'], function () {});
var oauth = {
clientId: argv.clientId || 'cid-webadmin',
clientSecret: argv.clientSecret || 'unused',
apiOrigin: argv.apiOrigin || '',
apiOriginHostname: argv.apiOrigin ? url.parse(argv.apiOrigin).hostname : ''
};
console.log();
console.log('Using OAuth credentials:');
console.log(' ClientId: %s', oauth.clientId);
console.log(' ClientSecret: %s', oauth.clientSecret);
console.log(' Cloudron API: %s', oauth.apiOrigin || 'default');
console.log(' Cloudron Host: %s', oauth.apiOriginHostname);
console.log();
gulp.task('js-index', function () {
// needs special treatment for error handling
var uglifyer = uglify();
uglifyer.on('error', function (error) {
console.error(error);
});
gulp.src([
'webadmin/src/js/index.js',
'webadmin/src/js/client.js',
'webadmin/src/js/appstore.js',
'webadmin/src/js/main.js',
'webadmin/src/views/*.js'
])
.pipe(ejs({ oauth: oauth }, { ext: '.js' }))
.pipe(sourcemaps.init())
.pipe(concat('index.js', { newLine: ';' }))
.pipe(uglifyer)
.pipe(sourcemaps.write())
.pipe(gulp.dest('webadmin/dist/js'));
});
gulp.task('js-setup', function () {
// needs special treatment for error handling
var uglifyer = uglify();
uglifyer.on('error', function (error) {
console.error(error);
});
gulp.src(['webadmin/src/js/setup.js', 'webadmin/src/js/client.js'])
.pipe(ejs({ oauth: oauth }, { ext: '.js' }))
.pipe(sourcemaps.init())
.pipe(concat('setup.js', { newLine: ';' }))
.pipe(uglifyer)
.pipe(sourcemaps.write())
.pipe(gulp.dest('webadmin/dist/js'));
});
gulp.task('js-setupdns', function () {
// needs special treatment for error handling
var uglifyer = uglify();
uglifyer.on('error', function (error) {
console.error(error);
});
gulp.src(['webadmin/src/js/setupdns.js', 'webadmin/src/js/client.js'])
.pipe(ejs({ oauth: oauth }, { ext: '.js' }))
.pipe(sourcemaps.init())
.pipe(concat('setupdns.js', { newLine: ';' }))
.pipe(uglifyer)
.pipe(sourcemaps.write())
.pipe(gulp.dest('webadmin/dist/js'));
});
gulp.task('js-update', function () {
// needs special treatment for error handling
var uglifyer = uglify();
uglifyer.on('error', function (error) {
console.error(error);
});
gulp.src(['webadmin/src/js/update.js'])
.pipe(sourcemaps.init())
.pipe(uglifyer)
.pipe(sourcemaps.write())
.pipe(gulp.dest('webadmin/dist/js'))
.pipe(gulp.dest('setup/splash/website/js'));
});
// --------------
// HTML
// --------------
gulp.task('html', ['html-views', 'html-update', 'html-templates'], function () {
return gulp.src('webadmin/src/*.html').pipe(ejs({ apiOriginHostname: oauth.apiOriginHostname }, { ext: '.html' })).pipe(gulp.dest('webadmin/dist'));
});
gulp.task('html-update', function () {
return gulp.src(['webadmin/src/update.html']).pipe(gulp.dest('setup/splash/website'));
});
gulp.task('html-views', function () {
return gulp.src('webadmin/src/views/**/*.html').pipe(gulp.dest('webadmin/dist/views'));
});
gulp.task('html-templates', function () {
return gulp.src('webadmin/src/templates/**/*.html').pipe(gulp.dest('webadmin/dist/templates'));
});
// --------------
// CSS
// --------------
gulp.task('css', function () {
return gulp.src('webadmin/src/*.scss')
.pipe(sourcemaps.init())
.pipe(sass({ includePaths: ['node_modules/bootstrap-sass/assets/stylesheets/'] }).on('error', sass.logError))
.pipe(autoprefixer())
.pipe(cssnano())
.pipe(sourcemaps.write())
.pipe(gulp.dest('webadmin/dist'))
.pipe(gulp.dest('setup/splash/website'));
});
gulp.task('images', function () {
return gulp.src('webadmin/src/img/**')
.pipe(gulp.dest('webadmin/dist/img'));
});
// --------------
// Utilities
// --------------
gulp.task('watch', ['default'], function () {
gulp.watch(['webadmin/src/*.scss'], ['css']);
gulp.watch(['webadmin/src/img/*'], ['images']);
gulp.watch(['webadmin/src/**/*.html'], ['html']);
gulp.watch(['webadmin/src/views/*.html'], ['html-views']);
gulp.watch(['webadmin/src/templates/*.html'], ['html-templates']);
gulp.watch(['webadmin/src/js/update.js'], ['js-update']);
gulp.watch(['webadmin/src/js/setup.js', 'webadmin/src/js/client.js'], ['js-setup']);
gulp.watch(['webadmin/src/js/setupdns.js', 'webadmin/src/js/client.js'], ['js-setupdns']);
gulp.watch(['webadmin/src/js/index.js', 'webadmin/src/js/client.js', 'webadmin/src/js/appstore.js', 'webadmin/src/js/main.js', 'webadmin/src/views/*.js'], ['js-index']);
gulp.watch(['webadmin/src/3rdparty/**/*'], ['3rdparty']);
});
gulp.task('clean', function () {
del.sync(['webadmin/dist', 'setup/splash/website']);
});
gulp.task('default', ['clean', 'html', 'js', '3rdparty', 'images', 'css'], function () {});
gulp.task('develop', ['watch'], serve({ root: 'webadmin/dist', port: 4000 }));

View File

@@ -1,32 +0,0 @@
#!/usr/bin/env node
'use strict';
var tar = require('tar-fs'),
fs = require('fs'),
path = require('path'),
zlib = require('zlib');
if (process.argv.length < 4) {
console.error('Usage: tarjs <cwd> <dir>');
process.exit(1);
}
var dir = process.argv[3];
var cwd = process.argv[2];
console.error('Packing directory "'+ dir +'" from within "' + cwd + '" and stream to stdout');
process.chdir(cwd);
var stat = fs.statSync(dir);
if (!stat.isDirectory()) throw(dir + ' is not a directory');
var gzipStream = zlib.createGzip({});
tar.pack(path.resolve(dir), {
ignore: function (name) {
if (name === '.') return true;
return false;
}
}).pipe(gzipStream).pipe(process.stdout);

View File

@@ -2,7 +2,7 @@
var async = require('async');
var ADMIN_GROUP_ID = 'admin'; // see groups.js
var ADMIN_GROUP_ID = 'admin'; // see constants.js
exports.up = function(db, callback) {
async.series([

View File

@@ -3,10 +3,10 @@
exports.up = function(db, callback) {
var cmd = "CREATE TABLE eventlog(" +
"id VARCHAR(128) NOT NULL," +
"source JSON," +
"source TEXT," +
"creationTime TIMESTAMP," +
"action VARCHAR(128) NOT NULL," +
"data JSON," +
"data TEXT," +
"PRIMARY KEY (id))";
db.runSql(cmd, function (error) {

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps ADD COLUMN robotsTxt TEXT', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps DROP COLUMN robotsTxt', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,29 @@
'use strict';
// we used to have JSON as the db type for those two, however mariadb does not support it
// and we never used any JSON related features, but have the TEXT pattern everywhere
// This ensures all old cloudrons will have the columns altered
exports.up = function(db, callback) {
db.runSql('ALTER TABLE eventlog MODIFY data TEXT', [], function (error) {
if (error) console.error(error);
db.runSql('ALTER TABLE eventlog MODIFY source TEXT', [], function (error) {
if (error) console.error(error);
callback(error);
});
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE eventlog MODIFY data TEXT', [], function (error) {
if (error) console.error(error);
db.runSql('ALTER TABLE eventlog MODIFY source TEXT', [], function (error) {
if (error) console.error(error);
callback(error);
});
});
};

View File

@@ -0,0 +1,16 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps ADD COLUMN enableBackup BOOLEAN DEFAULT 1', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps DROP COLUMN enableBackup', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE settings MODIFY value TEXT', [], function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE settings MODIFY value VARCHAR(512)', [], function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,25 @@
'use strict';
// ensure backupFolder and format are not empty
exports.up = function(db, callback) {
db.all('SELECT * FROM settings WHERE name=?', [ 'backup_config' ], function (error, result) {
if (error || result.length === 0) return callback(error);
var value = JSON.parse(result[0].value);
value.format = 'tgz'; // set the format
if (value.provider === 'filesystem' && !value.backupFolder) {
value.backupFolder = '/var/backups'; // set the backupFolder
}
db.runSql('UPDATE settings SET value = ? WHERE name = ?', [ JSON.stringify(value), 'backup_config' ], function (error) {
if (error) console.error('Error setting ownerid ' + JSON.stringify(u) + error);
callback();
});
});
};
exports.down = function(db, callback) {
callback();
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE backups ADD COLUMN format VARCHAR(16) DEFAULT "tgz"', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE backups DROP COLUMN format', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps ADD COLUMN newConfigJson TEXT', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps DROP COLUMN newConfigJson', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,40 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
async.series([
db.runSql.bind(db, 'ALTER TABLE backups ADD COLUMN manifestJson TEXT'),
db.runSql.bind(db, 'START TRANSACTION;'),
// fill all the backups with restoreConfigs from current apps
function addManifests(callback) {
console.log('Importing manifests');
db.all('SELECT * FROM backups WHERE type="app"', function (error, backups) {
if (error) return callback(error);
async.eachSeries(backups, function (backup, next) {
var m = backup.restoreConfigJson ? JSON.parse(backup.restoreConfigJson) : null;
if (m) m = JSON.stringify(m.manifest);
db.runSql('UPDATE backups SET manifestJson=? WHERE id=?', [ m, backup.id ], next);
}, callback);
});
},
db.runSql.bind(db, 'COMMIT'),
// remove the restoreConfig
db.runSql.bind(db, 'ALTER TABLE backups DROP COLUMN restoreConfigJson')
], callback);
};
exports.down = function(db, callback) {
async.series([
db.runSql.bind(db, 'ALTER TABLE backups DROP COLUMN manifestJson'),
db.runSql.bind(db, 'ALTER TABLE backups ADD COLUMN restoreConfigJson TEXT'),
], callback);
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps CHANGE newConfigJson updateConfigJson TEXT', [], function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps CHANGE updateConfigJson newConfigJson TEXT', [], function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps CHANGE lastBackupId restoreConfigJson TEXT', [], function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps CHANGE restoreConfigJson lastBackupId TEXT', [], function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,31 @@
'use strict';
// WARNING!!
// At this point the default db collation is utf8mb4_unicode_ci however we already have foreign key constraits
// already with tables on utf8_bin charset, so we cannot convert all tables here to utf8mb4 collation without
// a reimport from a sql dump, as foreign keys across different collations are not supported
var async = require('async');
exports.up = function(db, callback) {
async.series([
db.runSql.bind(db, 'ALTER TABLE appPortBindings CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE apps CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE authcodes CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE backups CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE clients CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE eventlog CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE groupMembers CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE groups CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE mailboxes CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE migrations CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE settings CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE tokens CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin'),
db.runSql.bind(db, 'ALTER TABLE users CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin')
], callback);
};
exports.down = function(db, callback) {
// nothing to be done here
callback();
};

View File

@@ -0,0 +1,70 @@
'use strict';
var async = require('async'),
safe = require('safetydance');
exports.up = function(db, callback) {
// first check precondtion of domain entry in settings
db.all('SELECT * FROM settings WHERE name = ?', [ 'domain' ], function (error, result) {
if (error) return callback(error);
var domain = {};
if (result[0]) domain = safe.JSON.parse(result[0].value) || {};
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
function addAppsDomainColumn(done) {
db.runSql('ALTER TABLE apps ADD COLUMN domain VARCHAR(128)', [], done);
},
function setAppDomain(done) {
if (!domain.fqdn) return done(); // skip for new cloudrons without a domain
db.runSql('UPDATE apps SET domain = ?', [ domain.fqdn ], done);
},
function addAppsLocationDomainUniqueConstraint(done) {
db.runSql('ALTER TABLE apps ADD UNIQUE location_domain_unique_index (location, domain)', [], done);
},
function removePresetupAdminGroupIfNew(done) {
// do not delete on update, will update the record in setMailboxesDomain()
if (domain.fqdn) return done();
// this will be finally created once we have a domain when we create the owner in user.js
const ADMIN_GROUP_ID = 'admin'; // see constants.js
db.runSql('DELETE FROM groups WHERE id = ?', [ ADMIN_GROUP_ID ], function (error) {
if (error) return done(error);
db.runSql('DELETE FROM mailboxes WHERE ownerId = ?', [ ADMIN_GROUP_ID ], done);
});
},
function addMailboxesDomainColumn(done) {
db.runSql('ALTER TABLE mailboxes ADD COLUMN domain VARCHAR(128)', [], done);
},
function setMailboxesDomain(done) {
if (!domain.fqdn) return done(); // skip for new cloudrons without a domain
db.runSql('UPDATE mailboxes SET domain = ?', [ domain.fqdn ], done);
},
function dropAppsLocationUniqueConstraint(done) {
db.runSql('ALTER TABLE apps DROP INDEX location', [], done);
},
db.runSql.bind(db, 'COMMIT')
], callback);
});
};
exports.down = function(db, callback) {
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
function dropMailboxesDomainColumn(done) {
db.runSql('ALTER TABLE mailboxes DROP COLUMN domain', [], done);
},
function dropLocationDomainUniqueConstraint(done) {
db.runSql('ALTER TABLE apps DROP INDEX location_domain_unique_index', [], done);
},
function dropAppsDomainColumn(done) {
db.runSql('ALTER TABLE apps DROP COLUMN domain', [], done);
},
function addAppsLocationUniqueConstraint(done) {
db.runSql('ALTER TABLE apps ADD UNIQUE location (location)', [], done);
},
db.runSql.bind(db, 'COMMIT')
], callback);
};

View File

@@ -0,0 +1,61 @@
'use strict';
var async = require('async'),
safe = require('safetydance'),
tld = require('tldjs');
exports.up = function(db, callback) {
var fqdn, zoneName, configJson;
async.series([
function gatherDomain(done) {
db.all('SELECT * FROM settings WHERE name = ?', [ 'domain' ], function (error, result) {
if (error) return done(error);
var domain = {};
if (result[0]) domain = safe.JSON.parse(result[0].value) || {};
fqdn = domain.fqdn || ''; // will be null pre-setup
zoneName = domain.zoneName || tld.getDomain(fqdn) || fqdn;
done();
});
},
function gatherDNSConfig(done) {
db.all('SELECT * FROM settings WHERE name = ?', [ 'dns_config' ], function (error, result) {
if (error) return done(error);
configJson = (result[0] && result[0].value) ? result[0].value : JSON.stringify({ provider: 'manual'});
// caas dns config needs an fqdn
var config = JSON.parse(configJson);
if (config.provider === 'caas') config.fqdn = fqdn;
configJson = JSON.stringify(config);
done();
});
},
db.runSql.bind(db, 'START TRANSACTION;'),
function createDomainsTable(done) {
var cmd = `
CREATE TABLE domains(
domain VARCHAR(128) NOT NULL UNIQUE,
zoneName VARCHAR(128) NOT NULL,
configJson TEXT,
PRIMARY KEY (domain)) CHARACTER SET utf8 COLLATE utf8_bin
`;
db.runSql(cmd, [], done);
},
function addInitialDomain(done) {
if (!fqdn) return done();
db.runSql('INSERT INTO domains (domain, zoneName, configJson) VALUES (?, ?, ?)', [ fqdn, zoneName, configJson ], done);
},
db.runSql.bind(db, 'COMMIT')
], callback);
};
exports.down = function(db, callback) {
db.runSql('DROP TABLE domains', callback);
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps ADD CONSTRAINT apps_domain_constraint FOREIGN KEY(domain) REFERENCES domains(domain)', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps DROP FOREIGN KEY apps_domain_constraint', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE mailboxes ADD CONSTRAINT mailboxes_domain_constraint FOREIGN KEY(domain) REFERENCES domains(domain)', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE mailboxes DROP FOREIGN KEY mailboxes_domain_constraint', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE mailboxes DROP PRIMARY KEY', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE mailboxes ADD PRIMARY KEY(name)', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE mailboxes ADD UNIQUE mailboxes_name_domain_unique_index (name, domain)', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE mailboxes DROP INDEX mailboxes_name_domain_unique_index', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps ADD COLUMN updateTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps DROP COLUMN updateTime', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps CHANGE createdAt creationTime TIMESTAMP(2) NOT NULL', [], function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps CHANGE creationTime createdAt TIMESTAMP(2) NOT NULL', [], function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,28 @@
'use strict';
var async = require('async');
// NOTE: This migration is incorrect because 'caas' domain is not guaranteed to be present in all Caas cloudrons
exports.up = function(db, callback) {
db.all('SELECT * FROM domains', function (error, domains) {
if (error) return callback(error);
var caasDomains = domains.filter(function (d) { return JSON.parse(d.configJson).provider === 'caas'; });
if (caasDomains.length === 0) return callback();
var caasDomain = caasDomains[0].domain;
db.all('SELECT * FROM settings WHERE name=?', [ 'backup_config' ], function (error, settings) {
if (error) return callback(error);
var setting = settings[0];
var config = JSON.parse(setting.value);
config.fqdn = caasDomain;
db.runSql('UPDATE settings SET value=? WHERE name=?', [ JSON.stringify(config), setting.name ], callback);
});
});
};
exports.down = function(db, callback) {
callback();
};

View File

@@ -0,0 +1,23 @@
'use strict';
exports.up = function(db, callback) {
var backupConfig = {
"provider": "filesystem",
"backupFolder": "/var/backups",
"format": "tgz",
"retentionSecs": 172800
};
db.runSql('INSERT settings (name, value) VALUES(?, ?)', [ 'backup_config', JSON.stringify(backupConfig) ], function (error) {
if (!error || error.code === 'ER_DUP_ENTRY') return callback(); // dup entry is OK for existing cloudrons
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('DELETE FROM settings WHERE name=?', ['backup_config'], function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,33 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
// first check precondtion of domain entry in settings
db.all('SELECT * FROM domains', [ ], function (error, domains) {
if (error) return callback(error);
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'ALTER TABLE domains ADD COLUMN provider VARCHAR(16) DEFAULT ""'),
function setProvider(done) {
async.eachSeries(domains, function (domain, iteratorCallback) {
var config = JSON.parse(domain.configJson);
var provider = config.provider;
delete config.provider;
db.runSql('UPDATE domains SET provider = ?, configJson = ? WHERE domain = ?', [ provider, JSON.stringify(config), domain.domain ], iteratorCallback);
}, done);
},
db.runSql.bind(db, 'ALTER TABLE domains MODIFY provider VARCHAR(16) NOT NULL'),
db.runSql.bind(db, 'COMMIT')
], callback);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE domains DROP COLUMN provider', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,24 @@
'use strict';
exports.up = function(db, callback) {
var cmd = 'CREATE TABLE IF NOT EXISTS mail(' +
'domain VARCHAR(128) NOT NULL UNIQUE,' +
'enabled BOOLEAN DEFAULT 0,' +
'mailFromValidation BOOLEAN DEFAULT 1,' +
'catchAllJson TEXT,' +
'relayJson TEXT,' +
'FOREIGN KEY(domain) REFERENCES domains(domain),' +
'PRIMARY KEY(domain)) CHARACTER SET utf8 COLLATE utf8_bin';
db.runSql(cmd, function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('DROP TABLE mail', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,34 @@
'use strict';
exports.up = function(db, callback) {
db.all('SELECT * FROM domains', function (error, domains) {
if (error) return callback(error);
if (domains.length === 0) return callback();
db.all('SELECT * FROM settings', function (error, allSettings) {
if (error) return callback(error);
// defaults
var mailFromValidation = true;
var catchAll = [ ];
var relay = { provider: 'cloudron-smtp' };
var mailEnabled = false;
allSettings.forEach(function (setting) {
switch (setting.name) {
case 'mail_from_validation': mailFromValidation = !!setting.value; break;
case 'catch_all_address': catchAll = JSON.parse(setting.value); break;
case 'mail_relay': relay = JSON.parse(setting.value); break;
case 'mail_config': mailEnabled = JSON.parse(setting.value).enabled; break;
}
});
db.runSql('INSERT INTO mail (domain, enabled, mailFromValidation, catchAllJson, relayJson) VALUES (?, ?, ?, ?, ?)',
[ domains[0].domain, mailEnabled, mailFromValidation, JSON.stringify(catchAll), JSON.stringify(relay) ], callback);
});
});
};
exports.down = function(db, callback) {
callback();
};

View File

@@ -0,0 +1,44 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
db.all('SELECT * FROM users', [ ], function (error, users) {
if (error) return callback(error);
db.all('SELECT * FROM mail WHERE enabled=1', [ ], function (error, mailDomains) {
if (error) return callback(error);
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'ALTER TABLE users DROP INDEX users_email'),
db.runSql.bind(db, 'ALTER TABLE users ADD COLUMN fallbackEmail VARCHAR(512) DEFAULT ""'),
function setDefaults(done) {
async.eachSeries(users, function (user, iteratorCallback) {
var defaultEmail = '';
var fallbackEmail = '';
if (mailDomains.length === 0) {
defaultEmail = user.email;
fallbackEmail = user.email;
} else {
defaultEmail = user.username ? (user.username + '@' + mailDomains[0].domain) : user.email;
fallbackEmail = user.email;
}
db.runSql('UPDATE users SET email = ?, fallbackEmail = ? WHERE id = ?', [ defaultEmail, fallbackEmail, user.id ], iteratorCallback);
}, done);
},
db.runSql.bind(db, 'ALTER TABLE users ADD UNIQUE users_email (email)'),
db.runSql.bind(db, 'COMMIT')
], callback);
});
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE users DROP COLUMN fallbackEmail', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,26 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
db.all('SELECT * FROM settings WHERE name = ?', [ 'tls_config' ], function (error, result) {
if (error) return callback(error);
var tlsConfig = (result[0] && result[0].value) ? JSON.parse(result[0].value) : { provider: 'letsencrypt-prod'};
tlsConfig.provider = tlsConfig.provider.replace(/$le\-/, 'letsencrypt-'); // old cloudrons had le-prod/le-staging
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'ALTER TABLE domains ADD COLUMN tlsConfigJson TEXT'),
db.runSql.bind(db, 'UPDATE domains SET tlsConfigJson = ?', [ JSON.stringify(tlsConfig) ]),
db.runSql.bind(db, 'COMMIT')
], callback);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE domains DROP COLUMN tlsConfigJson', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,47 @@
'use strict';
var async = require('async'),
fs = require('fs'),
superagent = require('superagent');
exports.up = function(db, callback) {
if (!fs.existsSync('/home/yellowtent/configs/cloudron.conf')) {
console.log('Unable to locate cloudron.conf');
return callback();
}
var config = JSON.parse(fs.readFileSync('/home/yellowtent/configs/cloudron.conf', 'utf8'));
if (config.provider !== 'caas' || !config.fqdn) {
console.log('Not caas (%s) or no fqdn', config.provider, config.fqdn);
return callback();
}
db.runSql('SELECT COUNT(*) AS total FROM users', function (error, result) {
if (error) return callback(error);
if (result[0].total === 0) {
console.log('This cloudron is not activated. It will automatically get appstore and caas configs from autoprovision logic');
return callback();
}
console.log('Downloading appstore and caas config');
superagent.get(config.apiServerOrigin + `/api/v1/boxes/${config.fqdn}/config`)
.query({ token: config.token })
.timeout(30 * 1000).end(function (error, result) {
if (error) return callback(error);
console.log('Adding %j config', result.body);
async.series([
db.runSql.bind(db, 'INSERT settings (name, value) VALUES(?, ?)', [ 'appstore_config', JSON.stringify(result.body.appstoreConfig) ]),
db.runSql.bind(db, 'INSERT settings (name, value) VALUES(?, ?)', [ 'caas_config', JSON.stringify(result.body.caasConfig) ])
], callback);
});
});
};
exports.down = function(db, callback) {
callback();
};

View File

@@ -0,0 +1,24 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
db.runSql('SELECT * FROM settings WHERE name=?', ['autoupdate_pattern'], function (error, results) {
if (error || results.length === 0) return callback(error); // will use defaults from box code
// migrate the 'daily' update pattern
var appUpdatePattern = results[0].value;
if (appUpdatePattern === '00 00 1,3,5,23 * * *') appUpdatePattern = '00 30 1,3,5,23 * * *';
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'DELETE FROM settings WHERE name=?', ['autoupdate_pattern']),
db.runSql.bind(db, 'INSERT settings (name, value) VALUES(?, ?)', ['app_autoupdate_pattern', appUpdatePattern]),
db.runSql.bind(db, 'COMMIT')
], callback);
});
};
exports.down = function(db, callback) {
callback();
};

View File

@@ -0,0 +1,121 @@
'use strict';
var async = require('async'),
crypto = require('crypto'),
fs = require('fs'),
os = require('os'),
path = require('path'),
safe = require('safetydance'),
tldjs = require('tldjs');
exports.up = function(db, callback) {
db.all('SELECT * FROM apps', function (error, apps) {
if (error) return callback(error);
async.eachSeries(apps, function (app, callback) {
if (!app.altDomain) {
console.log('App %s does not use altDomain, skip', app.id);
return callback();
}
const domain = tldjs.getDomain(app.altDomain);
const subdomain = tldjs.getSubdomain(app.altDomain);
const mailboxName = (subdomain ? subdomain : JSON.parse(app.manifestJson).title.toLowerCase().replace(/[^a-zA-Z0-9]/g, '')) + '.app';
console.log('App %s is on domain %s and subdomain %s with mailbox', app.id, domain, subdomain, mailboxName);
async.series([
// Add domain if not exists
function (callback) {
const query = 'INSERT INTO domains (domain, zoneName, provider, configJson, tlsConfigJson) VALUES (?, ?, ?, ?, ?)';
const args = [ domain, domain, 'manual', JSON.stringify({}), JSON.stringify({ provider: 'letsencrypt-prod' }) ];
db.runSql(query, args, function (error) {
if (error && error.code !== 'ER_DUP_ENTRY') return callback(error);
console.log('Added domain %s', domain);
// ensure we have a fallback cert for the newly added domain. This is the same as in reverseproxy.js
// WARNING this will only work on the cloudron itself not during local testing!
const certFilePath = `/home/yellowtent/boxdata/certs/${domain}.host.cert`;
const keyFilePath = `/home/yellowtent/boxdata/certs/${domain}.host.key`;
if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) { // generate it
let opensslConf = safe.fs.readFileSync('/etc/ssl/openssl.cnf', 'utf8');
let opensslConfWithSan = `${opensslConf}\n[SAN]\nsubjectAltName=DNS:${domain}\n`;
let configFile = path.join(os.tmpdir(), 'openssl-' + crypto.randomBytes(4).readUInt32LE(0) + '.conf');
let certCommand = `openssl req -x509 -newkey rsa:2048 -keyout ${keyFilePath} -out ${certFilePath} -days 3650 -subj /CN=*.${domain} -extensions SAN -config ${configFile} -nodes`;
safe.fs.writeFileSync(configFile, opensslConfWithSan, 'utf8');
if (!safe.child_process.execSync(certCommand)) return callback(safe.error.message);
safe.fs.unlinkSync(configFile);
}
callback();
});
},
// Add domain to mail table if not exists
function (callback) {
const query = 'INSERT INTO mail (domain, enabled, mailFromValidation, catchAllJson, relayJson) VALUES (?, ?, ?, ?, ?)';
const args = [ domain, 0, 1, '[]', JSON.stringify({ provider: 'cloudron-smtp' }) ];
db.runSql(query, args, function (error) {
if (error && error.code !== 'ER_DUP_ENTRY') return callback(error);
console.log('Added domain %s to mail table', domain);
callback();
});
},
// Remove old mailbox record if any
function (callback) {
const query = 'DELETE FROM mailboxes WHERE ownerId=?';
const args = [ app.id ];
db.runSql(query, args, function (error) {
if (error) return callback(error);
console.log('Cleaned up mailbox record for app %s', app.id);
callback();
});
},
// Add new mailbox record
function (callback) {
const query = 'INSERT INTO mailboxes (name, domain, ownerId, ownerType) VALUES (?, ?, ?, ?)';
const args = [ mailboxName, domain, app.id, 'app' /* mailboxdb.TYPE_APP */ ];
db.runSql(query, args, function (error) {
if (error) return callback(error);
console.log('Added mailbox record for app %s', app.id);
callback();
});
},
// Update app record
function (callback) {
const query = 'UPDATE apps SET location=?, domain=?, altDomain=? WHERE id=?';
const args = [ subdomain, domain, '', app.id ];
db.runSql(query, args, function (error) {
if (error) return error;
console.log('Updated app %s with new domain', app.id);
callback();
});
}
], callback);
}, function (error) {
if (error) return callback(error);
// finally drop the altDomain db field
db.runSql('ALTER TABLE apps DROP COLUMN altDomain', [], callback);
});
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps ADD COLUMN altDomain VARCHAR(256)', [], callback);
};

View File

@@ -0,0 +1,19 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'ALTER TABLE mailboxes DROP FOREIGN KEY mailboxes_domain_constraint'),
db.runSql.bind(db, 'ALTER TABLE mailboxes ADD CONSTRAINT mailboxes_domain_constraint FOREIGN KEY(domain) REFERENCES mail(domain)'),
db.runSql.bind(db, 'COMMIT')
], callback);
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE mailboxes DROP FOREIGN KEY mailboxes_domain_constraint', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,51 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
var users = { }, groupMembers = { };
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'ALTER TABLE mailboxes ADD COLUMN membersJson TEXT'),
function getUsers(done) {
db.all('SELECT * from users', [ ], function (error, results) {
if (error) return done(error);
results.forEach(function (result) { users[result.id] = result; });
done();
});
},
function getGroups(done) {
db.all('SELECT id, name, GROUP_CONCAT(groupMembers.userId) AS userIds ' +
' FROM groups LEFT OUTER JOIN groupMembers ON groups.id = groupMembers.groupId ' +
' GROUP BY groups.id', [ ], function (error, results) {
if (error) return done(error);
results.forEach(function (result) {
var userIds = result.userIds ? result.userIds.split(',') : [];
var members = userIds.map(function (id) { return users[id].username; });
groupMembers[result.id] = members;
});
done();
});
},
function removeGroupIdAndSetMembers(done) {
async.eachSeries(Object.keys(groupMembers), function (gid, iteratorDone) {
console.log(`Migrating group id ${gid} to ${JSON.stringify(groupMembers[gid])}`);
db.runSql('UPDATE mailboxes SET membersJson = ?, ownerId = ? WHERE ownerId = ?', [ JSON.stringify(groupMembers[gid]), 'admin', gid ], iteratorDone);
}, done);
},
db.runSql.bind(db, 'COMMIT')
], callback);
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE mailboxes DROP COLUMN membersJson', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,34 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'ALTER TABLE mailboxes ADD COLUMN type VARCHAR(16)'),
function addMailboxType(done) {
db.all('SELECT * from mailboxes', [ ], function (error, results) {
if (error) return done(error);
async.eachSeries(results, function (mailbox, iteratorCallback) {
let type = 'mailbox';
if (mailbox.aliasTarget) {
type = 'alias';
} else if (mailbox.membersJson) {
type = 'list';
}
db.runSql('UPDATE mailboxes SET type = ? WHERE name = ? AND domain = ?', [ type, mailbox.name, mailbox.domain ], iteratorCallback);
}, done);
});
},
db.runSql.bind(db, 'ALTER TABLE mailboxes MODIFY type VARCHAR(16) NOT NULL'),
db.runSql.bind(db, 'COMMIT')
], callback);
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE mailboxes DROP COLUMN membersJson', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE users ADD COLUMN twoFactorAuthenticationSecret VARCHAR(128) DEFAULT "", ADD COLUMN twoFactorAuthenticationEnabled BOOLEAN DEFAULT false', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE users DROP twoFactorAuthenticationSecret, DROP twoFactorAuthenticationEnabled', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,21 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('UPDATE clients SET scope=? WHERE id=? OR id=? OR id=?', ['*', 'cid-webadmin', 'cid-sdk', 'cid-cli'], function (error) {
if (error) console.error(error);
db.runSql('UPDATE tokens SET scope=? WHERE scope LIKE ?', ['*', '%*%'], function (error) { // remove the roleSdk
if (error) console.error(error);
db.runSql('UPDATE tokens SET expires=? WHERE clientId=?', [ 1525636734905, 'cid-webadmin' ], function (error) { // force webadmin to get a new token
if (error) console.error(error);
callback(error);
});
});
});
};
exports.down = function(db, callback) {
callback();
};

View File

@@ -0,0 +1,28 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
async.series([
db.runSql.bind(db, 'START TRANSACTION;'),
db.runSql.bind(db, 'ALTER TABLE apps ADD COLUMN ownerId VARCHAR(128)'),
function (next) {
db.all('SELECT id FROM users ORDER BY createdAt LIMIT 1', [ ], function (error, results) {
if (error || results.length === 0) return next(error);
var ownerId = results[0].id;
db.runSql('UPDATE apps SET ownerId=?', [ ownerId ], next);
});
},
db.runSql.bind(db, 'ALTER TABLE apps MODIFY ownerId VARCHAR(128) NOT NULL'),
db.runSql.bind(db, 'ALTER TABLE apps ADD CONSTRAINT apps_owner_constraint FOREIGN KEY(ownerId) REFERENCES users(id)'),
db.runSql.bind(db, 'COMMIT'),
], callback);
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps DROP COLUMN ownerId', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps ADD COLUMN ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE apps DROP COLUMN ts ', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,25 @@
'use strict';
exports.up = function(db, callback) {
var cmd = 'CREATE TABLE IF NOT EXISTS subdomains(' +
'appId VARCHAR(128) NOT NULL,' +
'domain VARCHAR(128) NOT NULL,' +
'subdomain VARCHAR(128) NOT NULL,' +
'type VARCHAR(128) NOT NULL,' +
'dnsRecordId VARCHAR(512),' +
'FOREIGN KEY(domain) REFERENCES domains(domain),' +
'FOREIGN KEY(appId) REFERENCES apps(id),' +
'UNIQUE (subdomain, domain)) CHARACTER SET utf8 COLLATE utf8_bin';
db.runSql(cmd, function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('DROP TABLE subdomains', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,28 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
db.all('SELECT * from apps', [ ], function (error, results) {
if (error) return done(error);
var queries = [
db.runSql.bind(db, 'START TRANSACTION;')
];
results.forEach(function (app) {
queries.push(db.runSql.bind(db, 'INSERT INTO subdomains (appId, domain, subdomain, type, dnsRecordId) VALUES (?, ?, ?, ?, ?)', [ app.id, app.domain, app.location, 'primary', app.dnsRecordId ]));
});
queries.push(db.runSql.bind(db, 'COMMIT'));
async.series(queries, callback);
});
};
exports.down = function(db, callback) {
db.runSql('DELETE FROM subdomains', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -0,0 +1,41 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
db.runSql('ALTER TABLE apps DROP INDEX location_domain_unique_index, DROP FOREIGN KEY apps_domain_constraint, DROP COLUMN domain, DROP COLUMN location, DROP COLUMN dnsRecordId', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.all('SELECT * from subdomains WHERE type = ?', [ 'primary' ], function (error, results) {
if (error) return callback(error);
var cmd = 'ALTER TABLE apps'
+ ' ADD COLUMN location VARCHAR(128),'
+ ' ADD COLUMN domain VARCHAR(128),'
+ ' ADD COLUMN dnsRecordId VARCHAR(512)';
db.runSql(cmd, function (error) {
if (error) return callback(error);
var queries = [ db.runSql.bind(db, 'START TRANSACTION;') ];
results.forEach(function (d) {
queries.push(db.runSql.bind(db, 'UPDATE apps SET domain = ?, location = ?, dnsRecordId = ? WHERE id = ?', [ d.domain, d.subdomain, d.appId, d.dnsRecordId ]));
});
queries.push(db.runSql.bind(db, 'COMMIT'));
async.series(queries, function (error) {
if (error) return callback(error);
var cmd = 'ALTER TABLE apps'
+ ' ADD CONSTRAINT apps_domain_constraint FOREIGN KEY(domain) REFERENCES domains(domain),'
+ ' ADD UNIQUE location_domain_unique_index (location, domain)';
db.runSql(cmd, callback);
});
});
});
};

View File

@@ -0,0 +1,15 @@
'use strict';
exports.up = function(db, callback) {
db.runSql('ALTER TABLE subdomains DROP COLUMN dnsRecordId', function (error) {
if (error) console.error(error);
callback(error);
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE subdomains ADD COLUMN dnsRecordId VARCHAR(512)', function (error) {
if (error) return callback(error);
callback();
});
};

View File

@@ -0,0 +1,34 @@
'use strict';
var async = require('async');
exports.up = function(db, callback) {
db.runSql('ALTER TABLE users ADD COLUMN admin BOOLEAN DEFAULT 0', function (error) {
if (error) return callback(error);
db.all('SELECT userId FROM groupMembers WHERE groupId=?', [ 'admin' ], function (error, results) {
if (error) return callback(error);
if (results.length === 0) return callback();
async.eachSeries(results, function (result, iteratorDone) {
db.runSql('UPDATE users SET admin=1 WHERE id=?', [ result.userId ], iteratorDone);
}, function (error) {
if (error) return callback(error);
async.series([
db.runSql.bind(db, 'DELETE FROM groupMembers WHERE groupId=?', [ 'admin' ]),
db.runSql.bind(db, 'DELETE FROM groups WHERE id=?', [ 'admin' ])
], callback);
});
});
});
};
exports.down = function(db, callback) {
db.runSql('ALTER TABLE users DROP COLUMN admin', function (error) {
if (error) console.error(error);
callback(error);
});
};

View File

@@ -9,6 +9,10 @@
#### BLOB - stored offline from table row (use for binary data)
#### https://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
# The code uses zero dates. Make sure sql_mode does NOT have NO_ZERO_DATE
# http://johnemb.blogspot.com/2014/09/adding-or-removing-individual-sql-modes.html
# SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'NO_ZERO_DATE',''));
CREATE TABLE IF NOT EXISTS users(
id VARCHAR(128) NOT NULL UNIQUE,
username VARCHAR(254) UNIQUE,
@@ -17,8 +21,12 @@ CREATE TABLE IF NOT EXISTS users(
salt VARCHAR(512) NOT NULL,
createdAt VARCHAR(512) NOT NULL,
modifiedAt VARCHAR(512) NOT NULL,
admin INTEGER NOT NULL,
displayName VARCHAR(512) DEFAULT '',
displayName VARCHAR(512) DEFAULT "",
fallbackEmail VARCHAR(512) DEFAULT "",
twoFactorAuthenticationSecret VARCHAR(128) DEFAULT "",
twoFactorAuthenticationEnabled BOOLEAN DEFAULT false,
admin BOOLEAN DEFAULT false,
PRIMARY KEY(id));
CREATE TABLE IF NOT EXISTS groups(
@@ -59,20 +67,27 @@ CREATE TABLE IF NOT EXISTS apps(
containerId VARCHAR(128),
manifestJson TEXT,
httpPort INTEGER, // this is the nginx proxy port and not manifest.httpPort
location VARCHAR(128) NOT NULL UNIQUE,
dnsRecordId VARCHAR(512), // tracks any id that we got back to track dns updates (unused)
location VARCHAR(128) NOT NULL,
domain VARCHAR(128) NOT NULL,
accessRestrictionJson TEXT, // { users: [ ], groups: [ ] }
createdAt TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP,
creationTime TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the app was installed
updateTime TIMESTAMP(2) NOT NULL DEFAULT CURRENT_TIMESTAMP, // when the last app update was done
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, // when this db record was updated (useful for UI caching)
memoryLimit BIGINT DEFAULT 0,
altDomain VARCHAR(256),
xFrameOptions VARCHAR(512),
sso BOOLEAN DEFAULT 1, // whether user chose to enable SSO
debugModeJson TEXT, // options for development mode
robotsTxt TEXT,
enableBackup BOOLEAN DEFAULT 1, // misnomer: controls automatic daily backups
// the following fields do not belong here, they can be removed when we use a queue for apptask
lastBackupId VARCHAR(128), // used to pass backupId to restore from to apptask
oldConfigJson TEXT, // used to pass old config for apptask
restoreConfigJson VARCHAR(256), // used to pass backupId to restore from to apptask
oldConfigJson TEXT, // used to pass old config to apptask (configure, restore)
updateConfigJson TEXT, // used to pass new config to apptask (update)
ownerId VARCHAR(128),
FOREIGN KEY(ownerId) REFERENCES users(id),
PRIMARY KEY(id));
CREATE TABLE IF NOT EXISTS appPortBindings(
@@ -91,7 +106,7 @@ CREATE TABLE IF NOT EXISTS authcodes(
CREATE TABLE IF NOT EXISTS settings(
name VARCHAR(128) NOT NULL UNIQUE,
value VARCHAR(512),
value TEXT,
PRIMARY KEY(name));
CREATE TABLE IF NOT EXISTS appAddonConfigs(
@@ -108,28 +123,70 @@ CREATE TABLE IF NOT EXISTS backups(
type VARCHAR(16) NOT NULL, /* 'box' or 'app' */
dependsOn TEXT, /* comma separate list of objects this backup depends on */
state VARCHAR(16) NOT NULL,
restoreConfigJson TEXT, /* JSON including the manifest of the backed up app */
manifestJson TEXT, /* to validate if the app can be installed in this version of box */
format VARCHAR(16) DEFAULT "tgz",
PRIMARY KEY (id));
CREATE TABLE IF NOT EXISTS eventlog(
id VARCHAR(128) NOT NULL,
action VARCHAR(128) NOT NULL,
source JSON, /* { userId, username, ip }. userId can be null for cron,sysadmin */
data JSON, /* free flowing json based on action */
creationTime TIMESTAMP, /* FIXME: precision must be TIMESTAMP(2) */
source TEXT, /* { userId, username, ip }. userId can be null for cron,sysadmin */
data TEXT, /* free flowing json based on action */
createdAt TIMESTAMP(2) NOT NULL,
PRIMARY KEY (id));
CREATE TABLE IF NOT EXISTS domains(
domain VARCHAR(128) NOT NULL UNIQUE, /* if this needs to be larger, InnoDB has a limit of 767 bytes for PRIMARY KEY values! */
zoneName VARCHAR(128) NOT NULL, /* this mostly contains the domain itself again */
provider VARCHAR(16) NOT NULL,
configJson TEXT, /* JSON containing the dns backend provider config */
tlsConfigJson TEXT, /* JSON containing the tls provider config */
PRIMARY KEY (domain))
/* the default db collation is utf8mb4_unicode_ci but for the app table domain constraint we have to use the old one */
CHARACTER SET utf8 COLLATE utf8_bin;
CREATE TABLE IF NOT EXISTS mail(
domain VARCHAR(128) NOT NULL UNIQUE,
enabled BOOLEAN DEFAULT 0, /* MDA enabled */
mailFromValidation BOOLEAN DEFAULT 1,
catchAllJson TEXT,
relayJson TEXT,
FOREIGN KEY(domain) REFERENCES domains(domain),
PRIMARY KEY(domain))
CHARACTER SET utf8 COLLATE utf8_bin;
/* Future fields:
* accessRestriction - to determine who can access it. So this has foreign keys
* quota - per mailbox quota
*/
CREATE TABLE IF NOT EXISTS mailboxes(
name VARCHAR(128) NOT NULL,
type VARCHAR(16) NOT NULL, /* 'mailbox', 'alias', 'list' */
ownerId VARCHAR(128) NOT NULL, /* app id or user id or group id */
ownerType VARCHAR(16) NOT NULL, /* 'app' or 'user' or 'group' */
aliasTarget VARCHAR(128), /* the target name type is an alias */
membersJson TEXT, /* members of a group */
creationTime TIMESTAMP,
domain VARCHAR(128),
PRIMARY KEY (name));
FOREIGN KEY(domain) REFERENCES mail(domain),
UNIQUE (name, domain));
CREATE TABLE IF NOT EXISTS subdomains(
appId VARCHAR(128) NOT NULL,
domain VARCHAR(128) NOT NULL,
subdomain VARCHAR(128) NOT NULL,
type VARCHAR(128) NOT NULL,
FOREIGN KEY(domain) REFERENCES domains(domain),
FOREIGN KEY(appId) REFERENCES apps(id),
UNIQUE (subdomain, domain))
CHARACTER SET utf8 COLLATE utf8_bin;

4927
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load Diff

8906
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,108 +1,101 @@
{
"name": "Cloudron",
"name": "cloudron",
"description": "Main code for a cloudron",
"version": "0.0.1",
"private": "true",
"version": "1.0.0",
"private": true,
"author": {
"name": "Cloudron authors"
},
"repository": {
"type": "git"
"type": "git",
"url": "https://git.cloudron.io/cloudron/box.git"
},
"engines": {
"node": ">=4.0.0 <=4.1.1"
},
"engines": [
"node >=4.0.0 <=4.1.1"
],
"dependencies": {
"@google-cloud/dns": "^0.7.2",
"@google-cloud/storage": "^1.7.0",
"@sindresorhus/df": "^2.1.0",
"async": "^2.1.4",
"aws-sdk": "^2.41.0",
"body-parser": "^1.13.1",
"cloudron-manifestformat": "^2.8.0",
"async": "^2.6.1",
"aws-sdk": "^2.253.1",
"body-parser": "^1.18.3",
"cloudron-manifestformat": "^2.11.0",
"connect-ensure-login": "^0.1.1",
"connect-lastmile": "^0.1.0",
"connect-timeout": "^1.5.0",
"connect-lastmile": "^1.0.2",
"connect-timeout": "^1.9.0",
"cookie-parser": "^1.3.5",
"cookie-session": "^1.1.0",
"cron": "^1.0.9",
"cookie-session": "^1.3.2",
"cron": "^1.3.0",
"csurf": "^1.6.6",
"db-migrate": "^0.10.0-beta.20",
"db-migrate": "^0.11.1",
"db-migrate-mysql": "^1.1.10",
"debug": "^2.2.0",
"dockerode": "^2.4.3",
"ejs": "^2.2.4",
"ejs-cli": "^1.2.0",
"express": "^4.12.4",
"express-session": "^1.11.3",
"gulp-sass": "^3.0.0",
"hat": "0.0.3",
"hock": "https://registry.npmjs.org/hock/-/hock-1.3.2.tgz",
"debug": "^3.1.0",
"dockerode": "^2.5.5",
"ejs": "^2.6.1",
"ejs-cli": "^2.0.1",
"express": "^4.16.3",
"express-session": "^1.15.6",
"json": "^9.0.3",
"ldapjs": "^1.0.0",
"mime": "^1.3.4",
"moment-timezone": "^0.5.5",
"morgan": "^1.7.0",
"multiparty": "^4.1.2",
"mysql": "^2.7.0",
"node-uuid": "^1.4.3",
"nodemailer": "^4.0.1",
"ldapjs": "^1.0.2",
"lodash.chunk": "^4.2.0",
"mime": "^2.3.1",
"moment-timezone": "^0.5.17",
"morgan": "^1.9.0",
"multiparty": "^4.1.4",
"mysql": "^2.15.0",
"nodemailer": "^4.6.5",
"nodemailer-smtp-transport": "^2.7.4",
"oauth2orize": "^1.0.1",
"oauth2orize": "^1.11.0",
"once": "^1.3.2",
"parse-links": "^0.1.0",
"passport": "^0.2.2",
"passport-http": "^0.2.2",
"passport": "^0.4.0",
"passport-http": "^0.3.0",
"passport-http-bearer": "^1.0.1",
"passport-local": "^1.0.0",
"passport-oauth2-client-password": "^0.1.2",
"password-generator": "^2.0.2",
"progress-stream": "^2.0.0",
"proxy-middleware": "^0.13.0",
"s3-block-read-stream": "^0.2.0",
"safetydance": "^0.2.0",
"semver": "^4.3.6",
"showdown": "^1.6.0",
"proxy-middleware": "^0.15.0",
"qrcode": "^1.2.0",
"readdirp": "^2.1.0",
"request": "^2.87.0",
"rimraf": "^2.6.2",
"s3-block-read-stream": "^0.5.0",
"safetydance": "^0.7.1",
"semver": "^5.5.0",
"showdown": "^1.8.6",
"speakeasy": "^2.0.0",
"split": "^1.0.0",
"superagent": "^1.8.3",
"supererror": "^0.7.1",
"tar-fs": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.15.2.tgz",
"tldjs": "^1.6.2",
"underscore": "^1.7.0",
"superagent": "^3.8.3",
"supererror": "^0.7.2",
"tar-fs": "^1.16.2",
"tar-stream": "^1.6.1",
"tldjs": "^2.3.1",
"underscore": "^1.9.1",
"uuid": "^3.2.1",
"valid-url": "^1.0.9",
"validator": "^4.9.0"
"validator": "^10.3.0",
"ws": "^5.2.0"
},
"devDependencies": {
"bootstrap-sass": "^3.3.3",
"deep-extend": "^0.4.1",
"del": "^1.1.1",
"expect.js": "*",
"gulp": "^3.8.11",
"gulp-autoprefixer": "^2.3.0",
"gulp-concat": "^2.4.3",
"gulp-cssnano": "^2.1.0",
"gulp-ejs": "^1.0.0",
"gulp-sass": "^3.0.0",
"gulp-serve": "^1.0.0",
"gulp-sourcemaps": "^1.5.2",
"gulp-uglify": "^1.1.0",
"hock": "~1.2.0",
"hock": "^1.3.2",
"istanbul": "*",
"js2xmlparser": "^1.0.0",
"mocha": "*",
"mock-aws-s3": "^2.4.0",
"nock": "^9.0.2",
"node-sass": "^3.0.0-alpha.0",
"readdirp": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
"request": "^2.65.0",
"yargs": "^3.15.0"
"js2xmlparser": "^3.0.0",
"mocha": "^5.2.0",
"mock-aws-s3": "git+https://github.com/cloudron-io/mock-aws-s3.git",
"nock": "^9.0.14",
"node-sass": "^4.6.1",
"recursive-readdir": "^2.2.2"
},
"scripts": {
"migrate_local": "DATABASE_URL=mysql://root:@localhost/box node_modules/.bin/db-migrate up",
"migrate_test": "BOX_ENV=test DATABASE_URL=mysql://root:@localhost/boxtest node_modules/.bin/db-migrate up",
"test": "npm run migrate_test && src/test/setupTest && BOX_ENV=test ./node_modules/istanbul/lib/cli.js test $1 ./node_modules/mocha/bin/_mocha -- -R spec ./src/test ./src/routes/test/[^a]*",
"test_all": "npm run migrate_test && src/test/setupTest && BOX_ENV=test ./node_modules/istanbul/lib/cli.js test $1 ./node_modules/mocha/bin/_mocha -- -R spec ./src/test ./src/routes/test",
"test": "npm run migrate_test && src/test/setupTest && BOX_ENV=test ./node_modules/istanbul/lib/cli.js test $1 ./node_modules/mocha/bin/_mocha -- --exit -R spec ./src/test ./src/routes/test/[^a]*",
"test_all": "npm run migrate_test && src/test/setupTest && BOX_ENV=test ./node_modules/istanbul/lib/cli.js test $1 ./node_modules/mocha/bin/_mocha -- --exit -R spec ./src/test ./src/routes/test",
"postmerge": "/bin/true",
"precommit": "/bin/true",
"prepush": "npm test",
"webadmin": "node_modules/.bin/gulp"
"dashboard": "node_modules/.bin/gulp"
}
}

122
scripts/cloudron-activate Executable file
View File

@@ -0,0 +1,122 @@
#!/bin/bash
set -eu -o pipefail
readonly curl="curl --fail --connect-timeout 20 --retry 10 --retry-delay 2 --max-time 2400"
function get_status() {
key="$1"
if status=$($curl -q -f "http://localhost:3000/api/v1/cloudron/status" 2>/dev/null); then
currentValue=$(echo "${status}" | python3 -c 'import sys, json; print(json.dumps(json.load(sys.stdin)[sys.argv[1]]))' "${key}")
echo "${currentValue}"
return 0
fi
return 1
}
function wait_for_status() {
key="$1"
expectedValue="$2"
echo "wait_for_status: $key to be $expectedValue"
while true; do
if currentValue=$(get_status "${key}"); then
echo "wait_for_status: $key is current: $currentValue expecting: $expectedValue"
if [[ "${currentValue}" == $expectedValue ]]; then
break
fi
fi
sleep 3
done
}
domain=""
domainProvider=""
domainConfigJson="{}"
domainTlsProvider="letsencrypt-prod"
adminUsername="superadmin"
adminPassword="Secret123#"
adminEmail="admin@server.local"
appstoreUserId=""
appstoreToken=""
backupDir="/var/backups"
args=$(getopt -o "" -l "domain:,domain-provider:,domain-tls-provider:,admin-username:,admin-password:,admin-email:,appstore-user:,appstore-token:,backup-dir:" -n "$0" -- "$@")
eval set -- "${args}"
while true; do
case "$1" in
--domain) domain="$2"; shift 2;;
--domain-provider) domainProvider="$2"; shift 2;;
--domain-tls-provider) domainTlsProvider="$2"; shift 2;;
--admin-username) adminUsername="$2"; shift 2;;
--admin-password) adminPassword="$2"; shift 2;;
--admin-email) adminEmail="$2"; shift 2;;
--appstore-user) appstoreUser="$2"; shift 2;;
--appstore-token) appstoreToken="$2"; shift 2;;
--backup-dir) backupDir="$2"; shift 2;;
--) break;;
*) echo "Unknown option $1"; exit 1;;
esac
done
echo "=> Waiting for cloudron to be ready"
wait_for_status "version" '*'
if [[ $(get_status "webadminStatus") != *'"tls": true'* ]]; then
echo "=> Domain setup"
dnsSetupData=$(printf '{ "domain": "%s", "adminFqdn": "%s", "provider": "%s", "config": %s, "tlsConfig": { "provider": "%s" } }' "${domain}" "my.${domain}" "${domainProvider}" "$domainConfigJson" "${domainTlsProvider}")
if ! $curl -X POST -H "Content-Type: application/json" -d "${dnsSetupData}" http://localhost:3000/api/v1/cloudron/dns_setup; then
echo "DNS Setup Failed"
exit 1
fi
wait_for_status "webadminStatus" '*"tls": true*'
else
echo "=> Skipping Domain setup"
fi
activationData=$(printf '{"username": "%s", "password":"%s", "email": "%s" }' "${adminUsername}" "${adminPassword}" "${adminEmail}")
if [[ $(get_status "activated") == "false" ]]; then
echo "=> Activating"
if ! activationResult=$($curl -X POST -H "Content-Type: application/json" -d "${activationData}" http://localhost:3000/api/v1/cloudron/activate); then
echo "Failed to activate with ${activationData}: ${activationResult}"
exit 1
fi
wait_for_status "activated" "true"
else
echo "=> Skipping Activation"
fi
echo "=> Getting token"
if ! activationResult=$($curl -X POST -H "Content-Type: application/json" -d "${activationData}" http://localhost:3000/api/v1/developer/login); then
echo "Failed to login with ${activationData}: ${activationResult}"
exit 1
fi
accessToken=$(echo "${activationResult}" | python3 -c 'import sys, json; print(json.load(sys.stdin)[sys.argv[1]])' "accessToken")
echo "=> Setting up App Store account with accessToken ${accessToken}"
appstoreData=$(printf '{"userId":"%s", "token":"%s" }' "${appstoreUser}" "${appstoreToken}")
if ! appstoreResult=$($curl -X POST -H "Content-Type: application/json" -d "${appstoreData}" "http://localhost:3000/api/v1/settings/appstore_config?access_token=${accessToken}"); then
echo "Failed to setup Appstore account with ${appstoreData}: ${appstoreResult}"
exit 1
fi
echo "=> Setting up Backup Directory with accessToken ${accessToken}"
backupData=$(printf '{"provider":"filesystem", "key":"", "backupFolder":"%s", "retentionSecs": 864000, "format": "tgz", "externalDisk": true}' "${backupDir}")
chown -R yellowtent:yellowtent "${backupDir}"
if ! backupResult=$($curl -X POST -H "Content-Type: application/json" -d "${backupData}" "http://localhost:3000/api/v1/settings/backup_config?access_token=${accessToken}"); then
echo "Failed to setup backup configuration with ${backupDir}: ${backupResult}"
exit 1
fi
echo "=> Done!"

View File

@@ -2,16 +2,6 @@
set -eu -o pipefail
if [[ ${EUID} -ne 0 ]]; then
echo "This script should be run as root." > /dev/stderr
exit 1
fi
if [[ $(lsb_release -rs) != "16.04" ]]; then
echo "Cloudron requires Ubuntu 16.04" > /dev/stderr
exit 1
fi
# change this to a hash when we make a upgrade release
readonly LOG_FILE="/var/log/cloudron-setup.log"
readonly DATA_FILE="/root/cloudron-install-data.json"
@@ -21,11 +11,21 @@ readonly MINIMUM_MEMORY="974" # this is mostly reported for 1GB main memory
readonly curl="curl --fail --connect-timeout 20 --retry 10 --retry-delay 2 --max-time 2400"
# copied from cloudron-resize-fs.sh
readonly rootfs_type=$(LC_ALL=C df --output=fstype / | tail -n1)
readonly physical_memory=$(LC_ALL=C free -m | awk '/Mem:/ { print $2 }')
readonly disk_size_bytes=$(LC_ALL=C df --output=size / | tail -n1)
readonly disk_size_gb=$((${disk_size_bytes}/1024/1024))
readonly RED='\033[31m'
readonly GREEN='\033[32m'
readonly DONE='\033[m'
# verify the system has minimum requirements met
if [[ "${rootfs_type}" != "ext4" ]]; then
echo "Error: Cloudron requires '/' to be ext4" # see #364
exit 1
fi
if [[ "${physical_memory}" -lt "${MINIMUM_MEMORY}" ]]; then
echo "Error: Cloudron requires atleast 1GB physical memory"
exit 1
@@ -36,105 +36,91 @@ if [[ "${disk_size_gb}" -lt "${MINIMUM_DISK_SIZE_GB}" ]]; then
exit 1
fi
if systemctl -q is-active box; then
echo "Error: Cloudron is already installed. To reinstall, start afresh"
exit 1
fi
initBaseImage="true"
# provisioning data
domain=""
provider=""
encryptionKey=""
restoreUrl=""
dnsProvider="manual"
tlsProvider="le-prod"
requestedVersion=""
apiServerOrigin="https://api.cloudron.io"
webServerOrigin="https://cloudron.io"
dataJson=""
prerelease="false"
sourceTarballUrl=""
rebootServer="true"
baseDataDir=""
# TODO this is still there for the restore case, see other occasions below
versionsUrl="https://s3.amazonaws.com/prod-cloudron-releases/versions.json"
args=$(getopt -o "" -l "domain:,help,skip-baseimage-init,data:,data-dir:,provider:,encryption-key:,restore-url:,tls-provider:,version:,dns-provider:,env:,prerelease,skip-reboot,source-url:" -n "$0" -- "$@")
args=$(getopt -o "" -l "help,skip-baseimage-init,data-dir:,provider:,version:,env:,prerelease,skip-reboot" -n "$0" -- "$@")
eval set -- "${args}"
while true; do
case "$1" in
--domain) domain="$2"; shift 2;;
--help) echo "See https://cloudron.io/references/selfhosting.html on how to install Cloudron"; exit 0;;
--help) echo "See https://cloudron.io/documentation/installation/ on how to install Cloudron"; exit 0;;
--provider) provider="$2"; shift 2;;
--encryption-key) encryptionKey="$2"; shift 2;;
--restore-url) restoreUrl="$2"; shift 2;;
--tls-provider) tlsProvider="$2"; shift 2;;
--dns-provider) dnsProvider="$2"; shift 2;;
--version) requestedVersion="$2"; shift 2;;
--env)
if [[ "$2" == "dev" ]]; then
versionsUrl="https://s3.amazonaws.com/dev-cloudron-releases/versions.json"
apiServerOrigin="https://api.dev.cloudron.io"
webServerOrigin="https://dev.cloudron.io"
tlsProvider="le-staging"
prerelease="true"
elif [[ "$2" == "staging" ]]; then
versionsUrl="https://s3.amazonaws.com/staging-cloudron-releases/versions.json"
apiServerOrigin="https://api.staging.cloudron.io"
webServerOrigin="https://staging.cloudron.io"
tlsProvider="le-staging"
prerelease="true"
fi
shift 2;;
--skip-baseimage-init) initBaseImage="false"; shift;;
--skip-reboot) rebootServer="false"; shift;;
--data) dataJson="$2"; shift 2;;
--prerelease) prerelease="true"; shift;;
--source-url) sourceTarballUrl="$2"; version="0.0.1+custom"; shift 2;;
--data-dir) baseDataDir=$(realpath "$2"); shift 2;;
--) break;;
*) echo "Unknown option $1"; exit 1;;
esac
done
# Only --help works as non-root
if [[ ${EUID} -ne 0 ]]; then
echo "This script should be run as root." > /dev/stderr
exit 1
fi
# Only --help works with mismatched ubuntu
if [[ $(lsb_release -rs) != "16.04" ]]; then
echo "Cloudron requires Ubuntu 16.04" > /dev/stderr
exit 1
fi
# validate arguments in the absence of data
if [[ -z "${dataJson}" ]]; then
if [[ -z "${provider}" ]]; then
echo "--provider is required (azure, digitalocean, ec2, lightsail, linode, ovh, rosehosting, scaleway, vultr or generic)"
exit 1
elif [[ \
"${provider}" != "ami" && \
"${provider}" != "azure" && \
"${provider}" != "digitalocean" && \
"${provider}" != "ec2" && \
"${provider}" != "gce" && \
"${provider}" != "lightsail" && \
"${provider}" != "linode" && \
"${provider}" != "ovh" && \
"${provider}" != "rosehosting" && \
"${provider}" != "scaleway" && \
"${provider}" != "vultr" && \
"${provider}" != "generic" \
]]; then
echo "--provider must be one of: azure, digitalocean, ec2, gce, lightsail, linode, ovh, rosehosting, scaleway, vultr or generic"
exit 1
fi
if [[ -z "${provider}" ]]; then
echo "--provider is required (azure, cloudscale, digitalocean, ec2, exoscale, hetzner, lightsail, linode, ovh, rosehosting, scaleway, vultr or generic)"
exit 1
elif [[ \
"${provider}" != "ami" && \
"${provider}" != "azure" && \
"${provider}" != "caas" && \
"${provider}" != "cloudscale" && \
"${provider}" != "digitalocean" && \
"${provider}" != "ec2" && \
"${provider}" != "exoscale" && \
"${provider}" != "gce" && \
"${provider}" != "hetzner" && \
"${provider}" != "lightsail" && \
"${provider}" != "linode" && \
"${provider}" != "ovh" && \
"${provider}" != "rosehosting" && \
"${provider}" != "scaleway" && \
"${provider}" != "vultr" && \
"${provider}" != "generic" \
]]; then
echo "--provider must be one of: azure, cloudscale.ch, digitalocean, ec2, exoscale, gce, hetzner, lightsail, linode, ovh, rosehosting, scaleway, vultr or generic"
exit 1
fi
if [[ "${tlsProvider}" != "fallback" && "${tlsProvider}" != "le-prod" && "${tlsProvider}" != "le-staging" ]]; then
echo "--tls-provider must be one of: le-prod, le-staging, fallback"
exit 1
fi
if [[ -z "${dnsProvider}" ]]; then
echo "--dns-provider is required (noop, manual)"
exit 1
elif [[ "${dnsProvider}" != "noop" && "${dnsProvider}" != "manual" ]]; then
echo "--dns-provider must be one of : manual, noop"
exit 1
fi
if [[ -n "${baseDataDir}" && ! -d "${baseDataDir}" ]]; then
echo "${baseDataDir} does not exist"
exit 1
fi
if [[ -n "${baseDataDir}" && ! -d "${baseDataDir}" ]]; then
echo "${baseDataDir} does not exist"
exit 1
fi
echo ""
@@ -145,7 +131,7 @@ echo ""
echo " Follow setup logs in a second terminal with:"
echo " $ tail -f ${LOG_FILE}"
echo ""
echo " Join us at https://chat.cloudron.io for any questions."
echo " Join us at https://forum.cloudron.io for any questions."
echo ""
if [[ "${initBaseImage}" == "true" ]]; then
@@ -162,74 +148,33 @@ if [[ "${initBaseImage}" == "true" ]]; then
fi
echo "=> Checking version"
if [[ "${sourceTarballUrl}" == "" ]]; then
if ! releaseJson=$($curl -s "${apiServerOrigin}/api/v1/releases?prerelease=${prerelease}&boxVersion=${requestedVersion}"); then
echo "Failed to get release information"
exit 1
fi
if ! releaseJson=$($curl -s "${apiServerOrigin}/api/v1/releases?prerelease=${prerelease}&boxVersion=${requestedVersion}"); then
echo "Failed to get release information"
exit 1
fi
if [[ "$requestedVersion" == "" ]]; then
version=$(echo "${releaseJson}" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["version"])')
else
version="${requestedVersion}"
fi
if [[ "$requestedVersion" == "" ]]; then
version=$(echo "${releaseJson}" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["version"])')
else
version="${requestedVersion}"
fi
if ! sourceTarballUrl=$(echo "${releaseJson}" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["info"]["sourceTarballUrl"])'); then
echo "No source code for version '${requestedVersion:-latest}'"
exit 1
fi
if ! sourceTarballUrl=$(echo "${releaseJson}" | python3 -c 'import json,sys;obj=json.load(sys.stdin);print(obj["info"]["sourceTarballUrl"])'); then
echo "No source code for version '${requestedVersion:-latest}'"
exit 1
fi
# Build data
# TODO versionsUrl is still there for the cloudron restore case
if [[ -z "${dataJson}" ]]; then
if [[ -z "${restoreUrl}" ]]; then
data=$(cat <<EOF
{
"boxVersionsUrl": "${versionsUrl}",
"fqdn": "${domain}",
"provider": "${provider}",
"apiServerOrigin": "${apiServerOrigin}",
"webServerOrigin": "${webServerOrigin}",
"tlsConfig": {
"provider": "${tlsProvider}"
},
"dnsConfig": {
"provider": "${dnsProvider}"
},
"backupConfig" : {
"provider": "filesystem",
"backupFolder": "/var/backups",
"key": "${encryptionKey}",
"retentionSecs": 172800
},
"updateConfig": {
"prerelease": ${prerelease}
},
"version": "${version}"
}
# from 1.9, we use autoprovision.json
data=$(cat <<EOF
{
"provider": "${provider}",
"apiServerOrigin": "${apiServerOrigin}",
"webServerOrigin": "${webServerOrigin}",
"version": "${version}"
}
EOF
)
else
data=$(cat <<EOF
{
"boxVersionsUrl": "${versionsUrl}",
"fqdn": "${domain}",
"provider": "${provider}",
"apiServerOrigin": "${apiServerOrigin}",
"webServerOrigin": "${webServerOrigin}",
"restore": {
"url": "${restoreUrl}",
"key": "${encryptionKey}"
},
"version": "${version}"
}
EOF
)
fi
else
data="${dataJson}"
fi
)
echo "=> Downloading version ${version} ..."
box_src_tmp_dir=$(mktemp -dt box-src-XXXXXX)
@@ -250,17 +195,9 @@ fi
echo "=> Installing version ${version} (this takes some time) ..."
echo "${data}" > "${DATA_FILE}"
# poor mans semver
if [[ ${version} == "0.10"* ]]; then
if ! /bin/bash "${box_src_tmp_dir}/scripts/installer.sh" --data-file "${DATA_FILE}" &>> "${LOG_FILE}"; then
echo "Failed to install cloudron. See ${LOG_FILE} for details"
exit 1
fi
else
if ! /bin/bash "${box_src_tmp_dir}/scripts/installer.sh" --data-file "${DATA_FILE}" --data-dir "${baseDataDir}" &>> "${LOG_FILE}"; then
echo "Failed to install cloudron. See ${LOG_FILE} for details"
exit 1
fi
if ! /bin/bash "${box_src_tmp_dir}/scripts/installer.sh" --data-file "${DATA_FILE}" --data-dir "${baseDataDir}" &>> "${LOG_FILE}"; then
echo "Failed to install cloudron. See ${LOG_FILE} for details"
exit 1
fi
rm "${DATA_FILE}"
@@ -268,20 +205,15 @@ echo -n "=> Waiting for cloudron to be ready (this takes some time) ..."
while true; do
echo -n "."
if status=$($curl -q -f "http://localhost:3000/api/v1/cloudron/status" 2>/dev/null); then
[[ -z "$domain" ]] && break # with no domain, we are up and running
[[ "$status" == *"\"tls\": true"* ]] && break # with a domain, wait for the cert
break # we are up and running
fi
sleep 10
done
if [[ -n "${domain}" ]]; then
echo -e "\n\nVisit https://my.${domain} to finish setup once the server has rebooted.\n"
else
echo -e "\n\nVisit https://<IP> to finish setup once the server has rebooted.\n"
fi
echo -e "\n\n${GREEN}Visit https://<IP> and accept the self-signed certificate to finish setup.${DONE}"
if [[ "${rebootServer}" == "true" ]]; then
echo -e "\n\nRebooting this server now to let bootloader changes take effect.\n"
echo -e "\n${RED}Rebooting this server now to let changes take effect.${DONE}\n"
systemctl stop mysql # sometimes mysql ends up having corrupt privilege tables
systemctl reboot
fi

View File

@@ -7,17 +7,15 @@ set -eu
[[ $(uname -s) == "Darwin" ]] && GNU_GETOPT="/usr/local/opt/gnu-getopt/bin/getopt" || GNU_GETOPT="getopt"
readonly GNU_GETOPT
args=$(${GNU_GETOPT} -o "" -l "revision:,output:" -n "$0" -- "$@")
args=$(${GNU_GETOPT} -o "" -l "output:" -n "$0" -- "$@")
eval set -- "${args}"
readonly SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
commitish="HEAD"
bundle_file=""
while true; do
case "$1" in
--revision) commitish="$2"; shift 2;;
--output) bundle_file="$2"; shift 2;;
--) break;;
*) echo "Unknown option $1"; exit 1;;
@@ -27,60 +25,56 @@ done
readonly TMPDIR=${TMPDIR:-/tmp} # why is this not set on mint?
if ! $(cd "${SOURCE_DIR}" && git diff --exit-code >/dev/null); then
echo "You have local changes, stash or commit them to proceed"
echo "You have local changes in box, stash or commit them to proceed"
exit 1
fi
if [[ "$(node --version)" != "v6.11.1" ]]; then
echo "This script requires node 6.11.1"
if ! $(cd "${SOURCE_DIR}/../dashboard" && git diff --exit-code >/dev/null); then
echo "You have local changes in dashboard, stash or commit them to proceed"
exit 1
fi
version=$(cd "${SOURCE_DIR}" && git rev-parse "${commitish}")
if [[ "$(node --version)" != "v8.11.2" ]]; then
echo "This script requires node 8.11.2"
exit 1
fi
box_version=$(cd "${SOURCE_DIR}" && git rev-parse "HEAD")
branch=$(git rev-parse --abbrev-ref HEAD)
if [[ "${branch}" == "master" ]]; then
dashboard_version=$(cd "${SOURCE_DIR}/../dashboard" && git rev-parse "${branch}")
else
dashboard_version=$(cd "${SOURCE_DIR}/../dashboard" && git fetch && git rev-parse "origin/${branch}")
fi
bundle_dir=$(mktemp -d -t box 2>/dev/null || mktemp -d box-XXXXXXXXXX --tmpdir=$TMPDIR)
[[ -z "$bundle_file" ]] && bundle_file="${TMPDIR}/box-${version}.tar.gz"
[[ -z "$bundle_file" ]] && bundle_file="${TMPDIR}/box-${box_version:0:10}-${dashboard_version:0:10}.tar.gz"
chmod "o+rx,g+rx" "${bundle_dir}" # otherwise extracted tarball director won't be readable by others/group
echo "Checking out code [${version}] into ${bundle_dir}"
(cd "${SOURCE_DIR}" && git archive --format=tar ${version} | (cd "${bundle_dir}" && tar xf -))
echo "==> Checking out code box version [${box_version}] and dashboard version [${dashboard_version}] into ${bundle_dir}"
(cd "${SOURCE_DIR}" && git archive --format=tar ${box_version} | (cd "${bundle_dir}" && tar xf -))
(cd "${SOURCE_DIR}/../dashboard" && git archive --format=tar ${dashboard_version} | (mkdir -p "${bundle_dir}/dashboard.build" && cd "${bundle_dir}/dashboard.build" && tar xf -))
(cp "${SOURCE_DIR}/../dashboard/LICENSE" "${bundle_dir}")
if diff "${TMPDIR}/boxtarball.cache/npm-shrinkwrap.json.all" "${bundle_dir}/npm-shrinkwrap.json" >/dev/null 2>&1; then
echo "Reusing dev modules from cache"
cp -r "${TMPDIR}/boxtarball.cache/node_modules-all/." "${bundle_dir}/node_modules"
else
echo "Installing modules with dev dependencies"
(cd "${bundle_dir}" && npm install)
echo "==> Installing modules for dashboard asset generation"
(cd "${bundle_dir}/dashboard.build" && npm install --production)
echo "Caching dev dependencies"
mkdir -p "${TMPDIR}/boxtarball.cache/node_modules-all"
rsync -a --delete "${bundle_dir}/node_modules/" "${TMPDIR}/boxtarball.cache/node_modules-all/"
cp "${bundle_dir}/npm-shrinkwrap.json" "${TMPDIR}/boxtarball.cache/npm-shrinkwrap.json.all"
fi
echo "==> Building dashboard assets"
(cd "${bundle_dir}/dashboard.build" && ./node_modules/.bin/gulp --revision ${dashboard_version})
echo "Building webadmin assets"
(cd "${bundle_dir}" && ./node_modules/.bin/gulp)
echo "==> Move built dashboard assets into destination"
mkdir -p "${bundle_dir}/dashboard"
mv "${bundle_dir}/dashboard.build/dist" "${bundle_dir}/dashboard/"
echo "Remove intermediate files required at build-time only"
rm -rf "${bundle_dir}/node_modules/"
rm -rf "${bundle_dir}/webadmin/src"
rm -rf "${bundle_dir}/gulpfile.js"
echo "==> Cleanup dashboard build artifacts"
rm -rf "${bundle_dir}/dashboard.build"
if diff "${TMPDIR}/boxtarball.cache/npm-shrinkwrap.json.prod" "${bundle_dir}/npm-shrinkwrap.json" >/dev/null 2>&1; then
echo "Reusing prod modules from cache"
cp -r "${TMPDIR}/boxtarball.cache/node_modules-prod/." "${bundle_dir}/node_modules"
else
echo "Installing modules for production"
(cd "${bundle_dir}" && npm install --production --no-optional)
echo "==> Installing toplevel node modules"
(cd "${bundle_dir}" && npm install --production --no-optional)
echo "Caching prod dependencies"
mkdir -p "${TMPDIR}/boxtarball.cache/node_modules-prod"
rsync -a --delete "${bundle_dir}/node_modules/" "${TMPDIR}/boxtarball.cache/node_modules-prod/"
cp "${bundle_dir}/npm-shrinkwrap.json" "${TMPDIR}/boxtarball.cache/npm-shrinkwrap.json.prod"
fi
echo "Create final tarball"
echo "==> Create final tarball"
(cd "${bundle_dir}" && tar czf "${bundle_file}" .)
echo "Cleaning up ${bundle_dir}"
echo "==> Cleaning up ${bundle_dir}"
rm -rf "${bundle_dir}"
echo "Tarball saved at ${bundle_file}"
echo "==> Tarball saved at ${bundle_file}"

View File

@@ -34,15 +34,50 @@ while true; do
esac
done
echo "==> installer: updating node"
if [[ "$(node --version)" != "v6.11.1" ]]; then
mkdir -p /usr/local/node-6.11.1
$curl -sL https://nodejs.org/dist/v6.11.1/node-v6.11.1-linux-x64.tar.gz | tar zxvf - --strip-components=1 -C /usr/local/node-6.11.1
ln -sf /usr/local/node-6.11.1/bin/node /usr/bin/node
ln -sf /usr/local/node-6.11.1/bin/npm /usr/bin/npm
rm -rf /usr/local/node-6.9.2
echo "==> installer: updating docker"
if [[ $(docker version --format {{.Client.Version}}) != "18.03.1-ce" ]]; then
$curl -sL https://download.docker.com/linux/ubuntu/dists/xenial/pool/stable/amd64/docker-ce_18.03.1~ce-0~ubuntu_amd64.deb -o /tmp/docker.deb
# https://download.docker.com/linux/ubuntu/dists/xenial/stable/binary-amd64/Packages
if [[ $(sha256sum /tmp/docker.deb | cut -d' ' -f1) != "54f4c9268492a4fd2ec2e6bcc95553855b025f35dcc8b9f60ac34e0aa307279b" ]]; then
echo "==> installer: docker binary download is corrupt"
exit 5
fi
echo "==> installer: Waiting for all dpkg tasks to finish..."
while fuser /var/lib/dpkg/lock; do
sleep 1
done
while ! dpkg --force-confold --configure -a; do
echo "==> installer: Failed to fix packages. Retry"
sleep 1
done
# the latest docker might need newer packages
while ! apt update -y; do
echo "==> installer: Failed to update packages. Retry"
sleep 1
done
while ! apt install -y /tmp/docker.deb; do
echo "==> installer: Failed to install docker. Retry"
sleep 1
done
rm /tmp/docker.deb
fi
echo "==> installer: updating node"
if [[ "$(node --version)" != "v8.11.2" ]]; then
mkdir -p /usr/local/node-8.11.2
$curl -sL https://nodejs.org/dist/v8.11.2/node-v8.11.2-linux-x64.tar.gz | tar zxvf - --strip-components=1 -C /usr/local/node-8.11.2
ln -sf /usr/local/node-8.11.2/bin/node /usr/bin/node
ln -sf /usr/local/node-8.11.2/bin/npm /usr/bin/npm
rm -rf /usr/local/node-6.11.5
fi
# this is here (and not in updater.js) because rebuild requires the above node
for try in `seq 1 10`; do
# for reasons unknown, the dtrace package will fail. but rebuilding second time will work
@@ -50,23 +85,34 @@ for try in `seq 1 10`; do
# however by default npm drops privileges for npm rebuild
# https://docs.npmjs.com/misc/config#unsafe-perm
if cd "${box_src_tmp_dir}" && npm rebuild --unsafe-perm; then break; fi
echo "Failed to rebuild, trying again"
echo "==> installer: Failed to rebuild, trying again"
sleep 5
done
if [[ ${try} -eq 10 ]]; then
echo "npm rebuild failed"
echo "==> installer: npm rebuild failed, giving up"
exit 4
fi
echo "==> installer: update cloudron-syslog"
CLOUDRON_SYSLOG_DIR=/usr/local/cloudron-syslog
CLOUDRON_SYSLOG="${CLOUDRON_SYSLOG_DIR}/bin/cloudron-syslog"
CLOUDRON_SYSLOG_VERSION="1.0.3"
while [[ ! -f "${CLOUDRON_SYSLOG}" || "$(${CLOUDRON_SYSLOG} --version)" != ${CLOUDRON_SYSLOG_VERSION} ]]; do
rm -rf "${CLOUDRON_SYSLOG_DIR}"
mkdir -p "${CLOUDRON_SYSLOG_DIR}"
if npm install --unsafe-perm -g --prefix "${CLOUDRON_SYSLOG_DIR}" cloudron-syslog@${CLOUDRON_SYSLOG_VERSION}; then break; fi
echo "===> installer: Failed to install cloudron-syslog, trying again"
sleep 5
done
if ! id "${USER}" 2>/dev/null; then
useradd "${USER}" -m
fi
if [[ "${is_update}" == "yes" ]]; then
echo "Setting up update splash screen"
"${box_src_tmp_dir}/setup/splashpage.sh" --data "${arg_data}" || true # show splash from new code
${BOX_SRC_DIR}/setup/stop.sh # stop the old code
echo "==> installer: stop cloudron.target service for update"
${BOX_SRC_DIR}/setup/stop.sh
fi
# setup links to data directory
@@ -81,9 +127,6 @@ fi
# ensure we are not inside the source directory, which we will remove now
cd /root
echo "==> installer: updating packages"
# add logic to update apt packages here
echo "==> installer: switching the box code"
rm -rf "${BOX_SRC_DIR}"
mv "${box_src_tmp_dir}" "${BOX_SRC_DIR}"

View File

@@ -3,25 +3,16 @@
source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
json="${source_dir}/../node_modules/.bin/json"
# IMPORTANT: Fix cloudron.js:doUpdate if you add/remove any arg. keep these sorted for readability
arg_api_server_origin=""
arg_fqdn=""
arg_is_custom_domain="false"
arg_restore_key=""
arg_restore_url=""
arg_fqdn="" # remove after 1.10
arg_admin_domain=""
arg_admin_location=""
arg_admin_fqdn=""
arg_retire_reason=""
arg_retire_info=""
arg_tls_config=""
arg_tls_cert=""
arg_tls_key=""
arg_token=""
arg_version=""
arg_web_server_origin=""
arg_backup_config=""
arg_dns_config=""
arg_update_config=""
arg_provider=""
arg_app_bundle=""
arg_is_demo="false"
args=$(getopt -o "" -l "data:,retire-reason:,retire-info:" -n "$0" -- "$@")
@@ -40,9 +31,13 @@ while true; do
--data)
# these params must be valid in all cases
arg_fqdn=$(echo "$2" | $json fqdn)
arg_admin_fqdn=$(echo "$2" | $json adminFqdn)
arg_is_custom_domain=$(echo "$2" | $json isCustomDomain)
[[ "${arg_is_custom_domain}" == "" ]] && arg_is_custom_domain="true"
arg_admin_location=$(echo "$2" | $json adminLocation)
[[ "${arg_admin_location}" == "" ]] && arg_admin_location="my"
arg_admin_domain=$(echo "$2" | $json adminDomain)
[[ "${arg_admin_domain}" == "" ]] && arg_admin_domain="${arg_fqdn}"
# only update/restore have this valid (but not migrate)
arg_api_server_origin=$(echo "$2" | $json apiServerOrigin)
@@ -50,43 +45,16 @@ while true; do
arg_web_server_origin=$(echo "$2" | $json webServerOrigin)
[[ "${arg_web_server_origin}" == "" ]] && arg_web_server_origin="https://cloudron.io"
# TODO check if an where this is used
# TODO check if and where this is used
arg_version=$(echo "$2" | $json version)
# read possibly empty parameters here
arg_app_bundle=$(echo "$2" | $json appBundle)
[[ "${arg_app_bundle}" == "" ]] && arg_app_bundle="[]"
arg_is_demo=$(echo "$2" | $json isDemo)
[[ "${arg_is_demo}" == "" ]] && arg_is_demo="false"
arg_tls_cert=$(echo "$2" | $json tlsCert)
[[ "${arg_tls_cert}" == "null" ]] && arg_tls_cert=""
arg_tls_key=$(echo "$2" | $json tlsKey)
[[ "${arg_tls_key}" == "null" ]] && arg_tls_key=""
arg_token=$(echo "$2" | $json token)
arg_provider=$(echo "$2" | $json provider)
[[ "${arg_provider}" == "" ]] && arg_provider="generic"
arg_tls_config=$(echo "$2" | $json tlsConfig)
[[ "${arg_tls_config}" == "null" ]] && arg_tls_config=""
arg_restore_url=$(echo "$2" | $json restore.url)
[[ "${arg_restore_url}" == "null" ]] && arg_restore_url=""
arg_restore_key=$(echo "$2" | $json restore.key)
[[ "${arg_restore_key}" == "null" ]] && arg_restore_key=""
arg_backup_config=$(echo "$2" | $json backupConfig)
[[ "${arg_backup_config}" == "null" ]] && arg_backup_config=""
arg_dns_config=$(echo "$2" | $json dnsConfig)
[[ "${arg_dns_config}" == "null" ]] && arg_dns_config=""
arg_update_config=$(echo "$2" | $json updateConfig)
[[ "${arg_update_config}" == "null" ]] && arg_update_config=""
shift 2
;;
--) break;;
@@ -96,15 +64,8 @@ done
echo "Parsed arguments:"
echo "api server: ${arg_api_server_origin}"
echo "admin fqdn: ${arg_admin_fqdn}"
echo "fqdn: ${arg_fqdn}"
echo "custom domain: ${arg_is_custom_domain}"
echo "restore url: ${arg_restore_url}"
echo "tls cert: ${arg_tls_cert}"
# do not dump these as they might become available via logs API
#echo "restore key: ${arg_restore_key}"
#echo "tls key: ${arg_tls_key}"
#echo "token: ${arg_token}"
echo "tlsConfig: ${arg_tls_config}"
echo "version: ${arg_version}"
echo "web server: ${arg_web_server_origin}"
echo "provider: ${arg_provider}"

Some files were not shown because too many files have changed in this diff Show More