lastBackupId is only used as a "message" passing field for apptask restore.
Theoretically, this code somehow protects a race between the cleanup logic
and the restore apptask. this is unlikely to happen and adds unnecessary
complexity.
This is sometimes useful when an update gets stuck because of some
bug in backup logic.
Note that you cannot restore from this backend because nothing is
saved.
Starting them all at once, sometimes hogs cpu/memory too much
and makes the startup scripts of the addons error.
The new addons setup a .setup file to confirm initialization.
In a future commit, we can use those .setup files to check if
the addon has started up instead of a timeout
This easy fix should improve performance with newer browsers especially
for applications that require many files to be sent over the wire
*cough*Nextcloud11*cough*
NGINX blog post about HTTP/2 support: https://www.nginx.com/blog/nginx-1-9-5/
This gets the right error message on failures:
$ cloudron machine backup create
Waiting for backup to finish...backup failed: ENOENT: no such file or directory, open '/var/backups/2017-04-21-013900-584/app_7549c6a1-682e-4150-8b40-2c31a3fa92f7_2017-04-21-013900-591_v0.7.1.tar.gz'
This is the root cause of 926224bd5d.
0488aada9f caused a regression where
we setup addons in the restore code path. This meant that redis was
instantiated and running, changing the perms of the dir. Then when
the backup extract happens it fails as it has wrong permissions.
All Cloudron containers need to have the nameserver 172.18.0.1. This was
being done at the daemon level, however since there are also iptables
rules restricting access to the nameserver from containers that aren't
on the Cloudron Docker network, this broke DNS for non-Cloudron
containers.
Since the DNS is only required for Cloudron containers in the first
place, this patch specifies 172.18.0.1 as the nameserver when Cloudron
creates a container and reverts the change at the daemon level
Those are not mocked yet and require real aws things.
Change will follow for mocking. We should probably keep them optionally
working agains AWS directly to ensure things really work
This is only temporarily as moving away from btrfs snapshots,
we introduced a regression for app backups.
gnu tar fails to create tarballs if the files change during packing.
Explanation:
When proxying an HTTP request, nginx first fills up the memory buffers (set by proxy_buffer_size and proxy_buffers).
When these are full, it then writes them to a temporary file in batches of proxy_temp_file_write_size until it reaches proxy_max_temp_file_size.
When proxy_max_temp_file_size is not set, and a very large file is being served, it reaches the maximum of 1GB, and nginx begins to behave weirdly.
Sometimes on error we get random strings for the installationProgresss,
as those contain the upstream errors :-/
We now at least attempt to show that so the user may give us the real
error not some wrongly parsed bits from that.
In the long run we have to make that a real structure to give sane error
messages
The goal here is to simply add a rate limit to prevent brute
force password attacks.
Covered services includes:
(public) http, https, ssh, smtp, msa, imap, sieve
(private) postgres, redis, mysql, ldap, mongodb. msa
The private limits are higher because some apps will create
a db connection for each page request. Some apps like mailtrain
will send out lots of emails etc.
Note that apps that use SSO are ratelimited by the ldap limit.
Part of #187
Also remove rate-limit middleware
Test using something like:
ab -v 1 -n 1000 -c 10 -s 5 -m POST https://my.<doamain>/api/v1/developer/login
Part of #187
some disk types do not contain proper partition tables like on time4vps
the type is simfs. On those fdisk fails to access the partition table,
thus being unable to determine the size of the volume.
df does only return the real usable disk space by the user, thus we
lower the 20GB threshold to 18
Fixes#275
Apps like nextcloud set their own security headers ending up with having
them set twice. I am not 100% sure if our headers should win or if we
should not inject headers with nginx if the upstream app sets them already.
This looks like the more permissive case where we simply enforce our
values, regardless what the apps sets.
This also fixes the nextcloud/owncloud security checks which were
failing because the header values were duplicated, which results in
string concatenation of values from same headers.
Simple Auth used to provide auth over HTTP. The original motivation
behind this was this was a simple way to add Cloudron Auth integration.
Back in the day, Cloudron Auth was a requirement for apps but this is
not the case anymore.
This is currently not used by any app and having this might encourage
people to make Cloudron specific un-upstreamable changes.
This is required for the case where the box restarts apptasks.
For example, the server can reboot mid-way when apptask is running
(as in cloudron-setup + appBundle case) and then when it comes back
up it doesn't wait for the platform to be ready. And the apps fail
to install (mysql takes a bit to startup)
This is based on the existence of admin.conf nginx file.
The splash would create/overwrite that file, but it will depend on the
host.cert to be already created, which is only the case after domain
setup.
We have 4 properties related to the domain:
1) location, is the subdomain location without information how to craft
a fqdn on the client
2) fqdn, the intended domain to reach the app
3) altDomain, just the value for the external domain, merely a db record
value
4) cnameTarget, mostly for display purpose on the client, which
otherwise has no way to build the original cloudron local fqdn
The configure code path now ensures the volume which ends up
changing the ownership of the data directory. This means that the
redis container which is still running cannot write anymore
when it is re-created as part of setupAddons().
Just change ownership of top level directory. The subdirectores
like data/ redis/ are owned by containers which will chown
accordingly.
For some reason, docker devices are collected in collectd stats (despite
us collecting only ext4 and btrfs devices). They have the patter *docker*.
Fixes#222
mocha loads all the tests in same process. This means that when
we start a new test, the old state still persists. For event
listeners, this means that they get multiple duplicate event handlers.
This will anyways happen once a new EC2 instance is created from the ami
and this ensures we do not encounter an SSH disconnect error when
running the cloudron-setup script during image creation
We use only mysql, so updating this means a lot of unused db backends
like sqlite do not need to be built with gyp anymore.
Note that this version is not yet released as stable, but works fine for
us. The outstanding issues are not related to our use-case from what I
can tell.
Fixes#82
This is then in sync with selfhosting and ensures the init startup
sequence is in order, since the setup on its own creates unit files
which should run prior to services already running.
This hopefully fixes the mysql disconnect issues.
This prevents one from redirecting to some http-only subdomain.
For example, surfer in naked domain redirects to www subdomain
(which is on github pages...)
/tmp is not very secure. But the real reason is so that we can
re-run the setup script again should things fail.
/home/yellowtent/box/scripts/installer.sh --data-file /root/cloudron-update-data.json
The following packages will be DOWNGRADED:
docker-engine
0 upgraded, 0 newly installed, 1 downgraded, 0 to remove and 0 not upgraded.
E: Packages were downgraded and -y was used without --allow-downgrades.
The core issue we want to solve is to debug a running app.
Let's make it explicit that it is in debugging mode because
functions like update/backup/restore don't work.
Part of #171
This is as reporting the disk size may vary from the one selected when
creating the server. Eg EC2 20GB storage results in 21474836480 bytes
which in turn will be calculated as less than 20GB in the script
When turned off, it will put the app in a writable rootfs. This
allows us to debug live/production apps (like change start.sh) and
just get them up and running. Once turned off, this app cannot be
updated anymore (unless the force flag is set). This way we can
then update it using the CLI if we are convinced that the upcoming
update fixes the problem.
Part of #171
Using the bytes output will fix an issue where the disk size is reported
either as terrabyte or also megabyte.
So far we disallowed 1TB disks but allowed 20MB disks.
file mounting is fraught with problems wrt change notifications.
first, we must be carefule that the inode does not change.
second, changes outside container do not result in fs events inside the container.
haraka cache settings files and relies on fs events. So, even
though the file gets updated inside the container, haraka doesn't
see it.
https://github.com/docker/docker/issues/15793
We had all this logic because we allowed the user to create a CaaS
cloudron with a custom domain from the appstore. This flow has changed
now.
One can only set the DNS config after verification. Only thing that
is required is a domain check.
Because of the docker upgrade, dnsbl queries are failing again
since we are not using the unbound server from the containers.
For some reason, docker cannot query 127.0.0.1 (https://github.com/docker/docker/issues/14627).
Make unbound listed on the cloudron network and let docker proxy
DNS calls to unbound (docker always use the embedded DNS server
when using UDN).
See also #130
One idea was to use docker binary packages. However, docker binaries
are statically linked and are incompatible with devicemapper.
See https://github.com/docker/docker/issues/14035 for more info.
Holding will let the user turn on automatic updates for non-security
packages as well.
Fixes#183
When docker is not passed the --storage-driver option, it tries to
auto detect the storage driver. Roughly:
1. If existing storage paths like /var/lib/docker/aufs exist, it will
choose that driver.
2. It has a priority list of drivers to scan in order (driver.go)
As it stands the ordering is aufs, btrfs and then devicemapper.
3. Docker will attempt to "init" each driver. aufs, for example,
tests for insmod'ing aufs and also looks into /proc/filesystems.
The fact that we installed aufs-tools and linux drivers (for aufs
driver) was a programming error since we want docker to use devicemapper.
However, what is curious is why docker still ended up choosing devicemapper
despite having all aufs requirements (as we do not pass --storage-driver explicitly).
The answer is that "apt-get install aufs-tool linux-image-* docker-engine"
can install packages in any order! This means there is a race on how docker
chooses the storage engine. In most cases, since linux-image-* is a big package,
docker gets to install first and ends up using devicemapper since aufs module is not found yet.
For some people, linux-image-* possibly installs first and thus docker
chooses aufs!
Mystery solved.
Part of #183
For reasons unknown, the images build by the buildbot (which currently
uses btrfs), does not work with devicemapper.
Existing cloudrons with aufs will not be affected because docker will
just ignore it.
devmapper: Base device already exists and has filesystem xfs on it. User specified filesystem will be ignored.
Existing AUFS users can move to devicemapper either by restoring to
a new cloudron (recommended) OR
* systemctl stop box
* systemctl stop docker
* rm -rf /var/lib/docker
* Edit /home/yellowtent/data/INFRA_VERSION. Change the "version" field to "1"
* systemctl start docker
* systemctl start box # this will download images all over
Fixes#182
If we change the domain when dns settings are changed, then migration
fails because we callout to appstore API via the domain (for example,
backup url call will fail because it uses the new domain name).
appbackup_%s_%s-v%s.tar.gz -> app_%s_%s_v%s.tar.gz
drop 'backup'. rationale: it is known these files are backups
timestamp has '-'. rationale: colon in filename confuses tools like scp (they think it is a hostname)
backup_%s-v%s.tar.gz -> box_%s_v%s.tar.gz
drop 'backup' and name it 'box'. this makes it clear it related to the box backup
timestamp has '-'. rationale: colon in filename confuses tools like scp (they think it is a hostname)
Part of #159
Since we don't have cases like failing to charge credit card so far, the
only reason it can fail here is that the appstore token or userId is
incorrect/expired
Fixes#52
This redesigns how update works. installer.sh now rebuild the package,
stops the old code and starts the new code. Importantly, it does not
download the new package, this is left to the caller. cloudron-setup
downloads the code and calls installer.sh of the downloaded code.
Same goes for updater.sh. This means that installer.sh itself is now
easily updatable.
Part of #152
Docker uses an embedded DNS server (127.0.0.11) for user defined networks (UDN).
With the latest releases of docker, specifying 127.0.0.1 as --dns makes the
containers resolve 127.0.0.1 _inside_ the container's networking namespace
(not sure how it worked before this).
The next idea was to only specify --dns-search=. but this does not work.
This makes docker setup the containers to use 127.0.0.1 (or 127.0.0.11 for UDN).
In my mind, the UDN case should work but doesn't (not sure why).
So, the solution is to simply go with no --dns or --dns-search. Sadly,
setting dns-search just at container level does not work either :/ Strangely,
docker run --network=cloudron --dns-search=. appimage # does not work
docker run --network=cloudron appimage # works if you manually remove search from /etc/resolv.conf
So clearly, something inside docker triggers when one of the dns* options is set.
This means that #130 has to be fixed at app level (For Go, this means to use the cgo resolver).
The new DO images have a different label causing DO images to not boot
root@ubuntu-2gb-sfo1-01:~# e2label /dev/vda1
cloudimg-rootfs
net.ifnames=0 is used get unpredictable names as per
https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/.
Not sure why we want that.
Not sure about notsc and clocksource.
This change also preserves any existing cmdline
This is unused. But more importantly, it causes the cloudron to
internal error and the whole UI goes down just because we cannot
detect the IP via the generic sysinfo provider.
This code was here to check if user will get an admin certificate.
It doesn't work well for intranet cloudron's. The check is also not
complete since just DNS is not enough for LE to succeed, we also
require port forwarding.
We do not have real categories, but only do filtering
based on the tags an app mentions. This changes adds more such tags, so
one by one we should ensure the correct tags are used in each app.
Apps not part of any such category can be found by full text search
field in the ui
Fixes#114
This has come up often now where people need to install the cli just for
app restarts, or would click the restore button, picking up an older
backup, where a simple restart of the app would have been sufficient.
Did this now after live-chat user asking again for this while an app got
stuck without anything obvious in the app logs.
The marker is "=== sso ==="
The part before the marker is shown if sso i disabled,
the remaining part is shown when sso is enabled.
If no marker is found, the whole text is shown
With our current self-hosting installation process, this
is not longer required. It should be the users responsibility
to gain access to his server. For Cloudron managed hosting,
this does not apply as we always create servers with ssh keys.
Also do not tinker with the sshd configs. The user may choose
to use access via password.
Fixes#104
This ensures it can start and stop the box process.
Due to control-group setting to killall children
the updater itself would get killed if the box service
restarts
This needs to be reenabled, but I can't make out
why having it set makes the parent script stop
after calling an external one with /bin/bash,
even though the external one has a 0 exit code
This reverts commit 8e033dc387.
Lots of things in ursa-purejs is unimplemented. We get errors like:
/home/yellowtent/box/node_modules/ursa-purejs/lib/ursa.js:331
throw new Error("Unsupported operation : sign");
^
Error: Unsupported operation : sign
at Object.sign (/home/yellowtent/box/node_modules/ursa-purejs/lib/ursa.js:331:13)
at Object.sign (/home/yellowtent/box/node_modules/ursa-purejs/lib/ursa.js:624:27)
at /home/yellowtent/box/src/cert/acme.js:112:50
at /home/yellowtent/box/src/cert/acme.js:70:16
From this version on only a local /root/userdata.json
is supported. We will poll for that file every 5sec
The file is either uploaded via boxtask in caas or
the cli tool
the dmarc records depends on the DKIM signing as well. if the
cloudron is not using the cloudron mail service, that means that
the mails are not dkim signed and thus mails get rejected.
We do not use a floating IP for 3 reasons:
1. The PTR record is not set to floating IP.
2. The outbound interface is not changeable to floating IP.
3. there are reports that port 25 on floating IP is blocked.
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://github.com/cloudron-io/omniauth-cloudron) and Node.js [passport](https://github.com/cloudron-io/passport-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).
OAuth authentication is meant to be used by apps. An app can get an OAuth token using the
[oauth](addons.html#oauth) or [simpleauth](addons.html#simpleauth) addon.
[oauth](addons.html#oauth) addon.
Tokens obtained via OAuth have a restricted scope wherein they can only access the user's profile.
This restriction is so that apps cannot make undesired changes to the user's Cloudron.
@@ -117,6 +117,7 @@ Request:
cert: <string>, // pem encoded TLS cert
key: <string>, // pem encoded TLS key
memoryLimit: <number>, // memory constraint in bytes
backupId: <string>, // initialize the app from this backup
altDomain: <string>, // alternate domain from which this app can be reached
xFrameOptions: <string> // set X-Frame-Options header, to control which websites can embed this app
}
@@ -151,6 +152,10 @@ If `altDomain` is set, the app can be accessed from `https://<altDomain>`.
*`SAMEORIGIN` - allows embedding from the same domain as the app. This is the default.
*`ALLOW-FROM https://example.com/` - allows this app to be embedded from example.com
`memoryLimit` is the maximum memory this app can use (in bytes) including swap. If set to 0, the app uses the `memoryLimit` value set in the manifest. If set to -1, the app gets unlimited memory.
If `backupId` is provided the app will be initialized with the data from the backup.
Read more about the options at [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).
Response (200):
@@ -197,7 +202,8 @@ Response (200):
health: <enum>, // health of the application
location: <string>, // subdomain on which app is installed
fqdn: <string>, // the FQDN of this app
altDomain: <string> // alternate domain from which this app can be reached
altDomain: <string>, // alternate domain from which this app can be reached
cnameTarget: <string> || null, // If altDomain is set, this contains the CNAME location for the app
accessRestriction: null || { // list of users and groups who can access this application
users: [ ],
groups: [ ]
@@ -207,7 +213,8 @@ Response (200):
portBindings: { // mapping from application ports to public ports
},
iconUrl: <url>, // a relative url providing the icon
memoryLimit: <number> // memory constraint in bytes
memoryLimit: <number>, // memory constraint in bytes
sso: <boolean> // Enable single sign-on
}
```
@@ -255,6 +262,8 @@ is integrated with Cloudron Authentication.
`manifest` is the [application manifest](/references/manifest.html).
For apps that support optional single sign-on, the `sso` field can be used to disable Cloudron authentication. By default, single sign-on is enabled.
### List apps
GET `/api/v1/apps/:appId` <scope>admin</scope>
@@ -276,7 +285,8 @@ Response (200):
health: <enum>, // health of the application
location: <string>, // subdomain on which app is installed
fqdn: <string>, // the FQDN of this app
altDomain: <string> // alternate domain from which this app can be reached
altDomain: <string>, // alternate domain from which this app can be reached
cnameTarget: <string> || null, // If altDomain is set, this contains the CNAME location for the app
accessRestriction: null || { // list of users and groups who can access this application
users: [ ],
groups: [ ]
@@ -315,7 +325,7 @@ GET `/api/v1/apps/:appId/backups` <scope>admin</scope>
Gets the backups of the application with id `appId`.
Use the [Backup](/references/api.html#download-backup) API to download the backup.
Use the [Backup](/references/api.html#download-backup) API to download the backup. Use the [Clone](/references/api.html#clone) API to create another instance of this app from a backup.
Response (200):
@@ -447,7 +457,7 @@ POST `/api/v1/apps/:appId/configure` <scope>admin</scope>
Re-configures an existing app with id `appId`.
Configuring an app won't preserve existing data. Cloudron apps are written in a way to support reconfiguring
Configuring an app preserves existing data. Cloudron apps are written in a way to support reconfiguring
any of the parameters listed below without loss of data.
monotonicTimestamp: <number>, // time passed since boot
message: [ <byte>,... ], // utf8 buffer
source: <process name> // source of this message
}
```
### List events
GET `/api/v1/eventlog` <scope>admin</scope>
GET `/api/v1/cloudron/eventlog` <scope>admin</scope>
Lists all the past events.
@@ -804,13 +900,13 @@ Response (200):
* user.remove
* user.update
`source` contains information on the originator of the action. For example, for user.login, this contains the IP address, the appId and the authType (ldap or simpleauth or oauth).
`source` contains information on the originator of the action. For example, for user.login, this contains the IP address, the appId and the authType (ldap or oauth).
`data` contains information on the event itself. For example, for user.login, this contains the userId that logged in. For app.install, it contains the manifest and location of the app that was installed.
To list all the app installation events:
```
curl -X GET -H 'Authorization: Bearer cb0463455a6606482be7956fc3abd53330ae23244e3492cda3914a2c5154c47e' https://my-demo.cloudron.me/api/v1/eventlog?action=app.install
curl -X GET -H 'Authorization: Bearer cb0463455a6606482be7956fc3abd53330ae23244e3492cda3914a2c5154c47e' https://my-demo.cloudron.me/api/v1/cloudron/eventlog?action=app.install
```
## Groups
@@ -860,6 +956,20 @@ Response (200):
}
```
### Set members
PUT `/api/v1/groups/:groupId/members` <scope>admin</scope>
Sets the members of an existing group with id `groupId`. Note that this replaces the
existing users with the provided userIds.
Request:
```
{
userIds: [ <string>, ... ] // list of users to be part of this group
}
```
### List groups
GET `/api/v1/groups` <scope>admin</scope>
@@ -893,125 +1003,6 @@ Response (204):
{}
```
## Mailboxes
Mailboxes allow users to receive mail using `IMAP`. Every user gets a mailbox with the same name as the username.
Users can receive email using IMAP (TLS) at `my.customdomain.com` and send mail using SMTP (STARTTLS) at
`my.customdomain.com`.
Apps can also receive email using the [recvmail addon](/references/addons.html#recvmail). App mailboxes are
named as `<subdomain>.app`. For this reason, the `.app` suffix is reserved for apps.
### Create mailbox
POST `/api/v1/mailboxes` <scope>admin</scope>
Creates a new mailbox.
`name` specifies the address at which email can be received and does not include the domain name. `name` can contain
only alphanumeric characters and a dot ('.') and must be lower case. The Cloudron mail server support '+' based subaddressing (i.e)name+tag@domain.com will be delivered to this mailbox.
mailboxes can only be accessed by users with the same username as the mailbox. A mailbox is automatically created
for every user on the Cloudron.
Request:
```
{
name: <string>
}
```
`name` must be atleast 2 characters and must be alphanumeric.
Response (200):
```
{
id: <string>,
name: <string>
}
```
### Get mailbox
GET `/api/v1/mailboxes/:mailboxName` <scope>admin</scope>
Gets an existing mailbox with name `mailboxName`.
Response (200):
```
{
id: <string>,
name: <string>,
aliases: [ <string>, ...]
}
```
### List mailboxes
GET `/api/v1/mailboxes` <scope>admin</scope>
Lists all mailboxes.
Response (200):
```
{
mailboxes: [
{
id: <string>,
name: <string>
},
...
]
}
```
### Set mailbox aliases
PUT `/api/v1/mailboxes/:mailboxName/aliases` <scope>admin</scope>
Sets aliases of an existing mailbox.
An alias is an alternate email address for a mailbox. Mails received at the alternate address are stored
in the mailbox. The email's `to` header should indicate the address that the original sent it to.
This also allows users to send emails with `From` address set to an alias.
Note that this call will replace the current aliases for this mailbox, it does **not** merge the provided ones with the current aliases.
Aliases have to be unique and cannot conflict with existing aliases or mailbox names. Any conflict with result in a 409.
Request:
```
{
aliases: [ <string>, ... ]
}
```
### Get mailbox aliases
GET `/api/v1/mailboxes/:mailboxName/aliases` <scope>admin</scope>
Depending on your setup, you may need to run this as root.
The setup will take around 10-15 minutes.
On OS X, it is known to work with the `openssl` package from homebrew.
**cloudron-setup** takes the following arguments:
See [#14](https://git.cloudron.io/cloudron/cloudron-cli/issues/14) for more information.
*`--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.
### Windows
Optional arguments for installation:
The CLI tool does not work on Windows.
*`--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.
### Machine subcommands
You should now be able to run the `cloudron machine help` command in a shell.
*`--data-dir` is the path where Cloudron will store platform and application data. Note: data
directory must be an `ext4` filesystem.
```
create Creates a new Cloudron
restore Restores a Cloudron
migrate Migrates a Cloudron
update Upgrade or updates a Cloudron
eventlog Get Cloudron eventlog
logs Get Cloudron logs
ssh Get remote SSH connection
backup Manage Cloudron backups
```
Optional arguments used for update and restore:
## AWS EC2
*`--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.
### Requirements
*`--restore-url` is a backup URL to restore from.
To run the Cloudron on AWS, first sign up with [Amazon AWS](https://aws.amazon.com/).
## Domain setup
The Cloudron uses the following AWS services:
Once the setup script completes, the server will reboot, then visit your server by its
IP address (`https://ip`) to complete the installation.
* **EC2** for creating a virtual private server that runs the Cloudron code.
* **Route53** for DNS. The Cloudron will manage all app subdomains as well as the email related DNS records automatically.
* **S3** to store encrypted Cloudron backups.
The setup website will show a certificate warning. Accept the self-signed certificate
and proceed to the domain setup.
The minimum requirements for a Cloudron depends on the apps installed. The absolute minimum required EC2 instance is `t2.small`.
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.
The Cloudron runs best on instances which do not have a burst mode VCPU.
### Route 53
The system disk space usage of a Cloudron is around 15GB. This results in a minimum requirement of about 30GB to give some headroom for app installations and user data.
Create root or IAM credentials and choose `Route 53` as the DNS provider.
### Cost Estimation
Taking the minimal requirements of hosting on EC2, with a backup retention of 2 days, the cost estimation per month is as follows:
```
Route53: 0.90
EC2: 19.04
EBS: 3.00
S3: 1.81
-------------------------
Total: $ 24.75/mth
```
For custom cost estimation, please use the [AWS Cost Calculator](http://calculator.s3.amazonaws.com/index.html)
### Setup
Open the AWS console and create the required resources:
1. Create a Route53 zone for your domain. Be sure to set the Route53 nameservers for your domain in your name registrar. Note: Only Second Level Domains are supported.
For example, `example.com`, `example.co.uk` will work fine. Choosing a domain name at any other level like `cloudron.example.com` will not work.
2. Create a S3 bucket for backups. The bucket region **must* be the same region as where you intend to create your Cloudron (EC2).
When creating the S3 bucket, it is important to choose a region. Do **NOT** choose `US Standard`.
The supported regions are:
* US East (N. Virginia) us-east-1
* US West (N. California) us-west-1
* US West (Oregon) us-west-2
* Asia Pacific (Mumbai) ap-south-1
* Asia Pacific (Seoul) ap-northeast-2
* Asia Pacific (Sydney) ap-southeast-2
* Asia Pacific (Tokyo) ap-northeast-1
* EU (Frankfurt) eu-central-1
* EU (Ireland) eu-west-1
* South America (São Paulo) sa-east-1
3. Create a new SSH key or upload an existing SSH key in the target region (`Key Pairs` in the left pane of the EC2 console).
4. Create AWS credentials. You can either use root **or** IAM credentials.
* 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:
* 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",
@@ -123,7 +142,55 @@ The supported regions are:
"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:*",
@@ -131,162 +198,313 @@ The supported regions are:
"arn:aws:s3:::<your bucket name>",
"arn:aws:s3:::<your bucket name>/*"
]
},
{
"Effect": "Allow",
"Action": "ec2:*",
"Resource": [
"*"
],
"Condition": {
"StringEquals": {
"ec2:Region": "<ec2 region>"
}
}
}
]
}
```
### Create the Cloudron
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.
Create the Cloudron using the `cloudron machine` command:
## 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.
The `--region` is the region where your Cloudron is to be created. For example, `us-west-1` for N. California and `eu-central-1` for Frankfurt. A complete list of available
regions is list <a href="//docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-available-regions" target="_blank">here</a>.
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 `--disk-size` parameter indicates the volume (hard disk) size to be allocated for the Cloudron.
The information to be copied to the Cloudron's backup settings form may look similar to:
The `--ssh-key` is the path to a PEM file or the private SSH Key. If your key is located as `~/.ssh/id_rsa_<name>`, you can
The `--backup-key '<secret>'` will be used to encrypt all backups prior to uploading to S3. Keep that secret in a safe place, as you need it to restore your Cloudron from a backup! You can generate a random key using `pwgen -1y 64`. Be sure to put single quotes
around the `secret` to prevent accidental shell expansion.
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.
**NOTE**: The `cloudron machine create` subcommand will automatically create a corresponding VPC, subnet and security group for your Cloudron, unless `--subnet` and `--security-group` arguments are explicitly passed in. If you want to reuse existing resources, please ensure that the security group does not limit any traffic to the Cloudron since the Cloudron manages its own firewall and that the subnet has an internet gateway setup in the routing table.
# Email
## First time setup
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.
Visit `https://my.<domain>` to do first time setup of your Cloudron.
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.
1. The website should already have a valid TLS certificate. If you see any certificate warnings, it means your Cloudron was not created correctly.
2. If you see a login screen, instead of a setup screen, it means that someone else got to your Cloudron first and set it up
already! In this unlikely case, simply delete the EC2 instance and create a new Cloudron again.
## Checklist
Once the setup is done, you can access the admin page in the future at `https://my.<domain>`.
* If you are unable to receive mail, first thing to check is if your VPS provider lets you
receive mail on port 25.
## Backups
* Digital Ocean - New accounts frequently have port 25 blocked. Write to their support to
unblock your server.
The Cloudron has a backup schedule of creating one once a day. In addition to regularly scheduled backups, a backup is also created if you update the Cloudron or any of the apps (in this case only the app in question will get backed up).
* EC2, Lightsail & Scaleway - Edit your security group to allow email.
Since this might result in a lot of backup data on your S3 backup bucket, we recommend adjusting the bucket properties. This can be done adding a lifecycle rule for that bucket, 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 already sufficient for most use-cases.
* 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:
If your Cloudron is running, you can list backups using the following command:
```
cloudron machine backup list <domain>
npm install -g cloudron
```
Alternately, you can list the backups by querying S3 using the following command:
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:
*`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:
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.
The backup id can be obtained by [listing the backup](/references/selfhosting.html#backups). Other arguments are similar to [Cloudron creation](/references/selfhosting.html#create-the-cloudron). Once the new instance has completely restored, you can safely terminate the old Cloudron from the AWS console.
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):
## Updates
Apps installed from the Cloudron Store are updated automatically every night.
The Cloudron platform itself updates in two ways:
* An **update** is applied onto the running server instance. Such updates are performed every night. You can use the Cloudron UI to perform updates.
* An **upgrade** requires a new OS image and thus has to be performed using the CLI tool. This process involves creating a new EC2 instance is created using the latest image and all the data and apps are restored. The `cloudron machine update` command can be used when an _upgrade_ is available (you will get a notification in the UI).
Once the upgrade is complete, you can safely terminate the old EC2 instance.
The Cloudron will always make a complete backup before attempting an update or upgrade. In the unlikely case an update fails, it can be [restored](/references/selfhosting.html#restore).
If you are unable to connect, verify the following:
* Be sure to use the **my.** subdomain (eg. my.foobar.com).
* The SSH Key should be in PEM format. If you are using Putty PPK files, follow [this article](http://stackoverflow.com/questions/2224066/how-to-convert-ssh-keypairs-generated-using-puttygenwindows-into-key-pairs-use) to convert it to PEM format.
* The SSH Key must have correct permissions (400) set (this is a requirement of the ssh client).
# Debug
## Mail
You can SSH into your Cloudron and collect logs:
Spammers frequently abuse EC2 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 automatically and reputation should be easy to get back.
*`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>`.
* Once your Cloudron is ready, apply for a Reverse DNS record to be setup for your domain. You can find the AWS request
form [here](https://aws-portal.amazon.com/gp/aws/html-forms-controller/contactus/ec2-email-limit-rdns-request).
# Alerts
* Check if your IP is listed in any DNSBL list [here](http://multirbl.valli.org/). In most cases, you can apply for removal
of your IP by filling out a form at the DNSBL manager site.
The Cloudron will notify the Cloudron administrator via email if apps go down, run out of memory, have updates
available etc.
* Finally, check your spam score at [mail-tester.com](https://www.mail-tester.com/).
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.
## Debugging
To debug the Cloudron CLI tool:
*`DEBUG=* cloudron <cmd>`
You can also [SSH](#ssh) into your Cloudron and collect logs.
*`journalctl -a -u box -u cloudron-installer` 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
containers log output, `journalctl -a CONTAINER_ID=<container_id>`.
## Other Providers
Currently, we do not support other cloud server provider. Please let us know at [support@cloudron.io](mailto:support@cloudron.io), if you want to see other providers supported.
## Help
If you run into any problems, join us in our [chat](https://chat.cloudron.io) or [email us](mailto:support@cloudron.io).
# Help
If you run into any problems, join us at our [chat](https://chat.cloudron.io) or [email us](mailto:support@cloudron.io).
@@ -247,7 +262,7 @@ Use the following settings to receive email.
* Connection Security - TLS
* Username/password - Same as your Cloudron credentials
### Sending email (SMTP)
## Sending email using SMTP
Use the following settings to send email.
@@ -256,7 +271,7 @@ Use the following settings to send email.
* Connection Security - STARTTLS
* Username/password - Same as your Cloudron credentials
### Email filters (Sieve)
## Email filters using Sieve
Use the following settings to setup email filtering users via Manage Sieve.
@@ -268,7 +283,7 @@ Use the following settings to setup email filtering users via Manage Sieve.
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
## 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.
@@ -278,12 +293,22 @@ user's settings, available behind the edit button in the user listing. Note that
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
## 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.
## Graphs
## 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.
@@ -298,32 +323,44 @@ 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
# 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">
## Domains and SSL Certificates
# 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.
## API Access
# OAuth Provider
All the operations listed in this manual like installing app, configuring users and groups, are
completely programmable with a [REST API](/references/api.html).
Cloudron is an OAuth 2.0 provider. To integrate Cloudron login into an external application, create
an OAuth application under `API Access`.
## Moving to a larger Cloudron
You can use the following OAuth URLs to add Cloudron in the external app:
@@ -188,7 +188,7 @@ 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.9.0
Step 1 : FROM cloudron/base:0.10.0
---> be9fc6312b2d
Step 2 : ADD server.js /app/code/server.js
---> 10513e428d7a
@@ -271,14 +271,18 @@ You can also execute arbitrary commands:
$ cloudron exec env # display the env variables that your app is running with
```
### DevelopmentMode
### Debugging
When debugging complex startup scripts, one can specify `"developmentMode": true,` in the CloudronManifest.json.
This will ignore the `RUN` command, specified in the Dockerfile and allows the developer to interactively test
the startup scripts using `cloudron exec`.
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`.
**Note:** that an app running in this mode has full read/write access to the filesystem and all memory limits are lifted.
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
@@ -331,7 +335,7 @@ See https://git.cloudron.io/cloudron/tutorial-ldap for a simple example of how t
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
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
@@ -344,12 +348,64 @@ show any setup screen after installation and should simply choose reasonable def
Databases, email configuration should be automatically picked up from the environment variables using
addons.
## Dockerfile
## Docker
The app is run as a read-only docker container. 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.
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:
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
@@ -358,7 +414,7 @@ automatically. If your application is a single process, you do not require any p
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 to child processes.
Be sure to pick a process manager that [forwards signals](#sigterm-handling) to child processes.
## Automatic updates
@@ -385,64 +441,244 @@ 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.
## Startup Script
## 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 launches the server. Before starting the server,
the `start.sh` script does the following:
a `start.sh` script (named so by convention) which is used as the app entry point.
* When using the `localstorage` addon, it changes the ownership of files in `/app/data` as desired using `chown`. This
is necessary because file permissions may not be correctly preserved across backup, restore, application and base image
updates.
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" ]
```
* 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.
### One-time init
* Finally, it starts the server as a non-root user.
One common pattern is to initialize the data directory with some commands once depending on the existence of a special `.initialized` file.
The app's main process must handle SIGTERM and forward it as required to child processes. bash does not
automatically forward signals to child processes. For this reason, when using a startup shell script,
remember to use exec <app> as the last line. Doing so will replace bash with your program and allows
your program to handle signals as required.
```sh
if ! [ -f /app/data/.initialized ]; then
echo "Fresh installation, setting up data directory..."
# Setup commands here
touch /app/data/.initialized
echo "Done."
fi
```
# Beta Testing
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:
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:
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 \
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.
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 upload
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.
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
## Publishing
Once you are satisfied with the beta testing, you can submit it for review.
```
cloudron submit
cloudron appstore submit
```
The cloudron.io team will review the app and publish the app to the store.
# Updating the app
## Versioning
## 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 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.
@@ -461,7 +697,7 @@ 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
update fail, the user can restore to the backup (which will also restore the app's
echo"Resizing up btrfs user data to size ${home_data_size}M"
umount "${USER_DATA_DIR}"||true
# Do not preallocate (non-sparse). Doing so overallocates for data too much in advance and causes problems when using many apps with smaller data
# fallocate -l "${home_data_size}m" "${USER_DATA_FILE}" # does not overwrite existing data
truncate -s "${home_data_size}m""${USER_DATA_FILE}"# this will shrink it if the file had existed. this is useful when running this script on a live system
mount -t btrfs -o loop,nosuid "${USER_DATA_FILE}"${USER_DATA_DIR}
# on ec2, without this we get a sporadic connection drop when doing the initial migration
max_allowed_packet=32M
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.