Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Add Docker Hub image #965

Merged

Conversation

leojonathanoh
Copy link

@leojonathanoh leojonathanoh commented Feb 15, 2023

Summary

This builds on the already-existing "stale" ./docker/release docker build context. As much as possible of the original docker image is retained, except for a few changes: 1) refactor to use alpine as the base image 2) Instead of a custom php-cli user, run as root and www-data, just like official docker hub nginx and php-fpm images. 3) Removed logrotate and tail -f since snappymail logs go directly to /dev/stderr instead of error.log 4) auth.log is preserved to be parsed by an external fail2ban container.

Since I'm not an approved collaborator on this repo, the CI cannot run on this PR. So I'm building the image on the same branch on my fork PR leojonathanoh#1. Try it out:

Docker hub repo: https://hub.docker.com/r/leojonathanoh/snappymail

# Latest build on PR
docker run --rm -it -p 8888:8888 leojonathanoh/snappymail:pr-1
# Or a specific build on PR
docker run --rm -it -p 8888:8888 leojonathanoh/snappymail:pr-1-<sha>

GitHub Container Registry: https://github.com/leojonathanoh/snappymail/pkgs/container/snappymail

# Latest build on PR
docker run --rm -it -p 8888:8888 ghcr.io/leojonathanoh/snappymail:pr-1
# Or a specific build on PR
docker run --rm -it -p 8888:8888 ghcr.io/leojonathanoh/snappymail:pr-1-<sha>

Dockefile:

  • Change to multi-stage Dockerfile
  • Patch release.php so it works to create a release .tar.gz
  • Refactor final base image to alpine which will run supervisord, nginx, and php-fpm. All php extensions are preserved. More php extensions may be added.
  • The php-cli user in the image is removed. Instead of running all processes as php-cli user, supervisord runs as root, nginx master runs as root (like official nginx docker image), php-fpm master process runs as root (like official nginx docker image)

entrypoint.sh:

  • Move 4 env vars from Dockerfile to entrypoint.sh. This allows users to be able to customize the php-fpm config via env vars.
  • Remove sed -z since it's not posix-compatible.
  • Replace php-cli user with root and www-data

php-fpm.conf:

  • Replace php-cli user with root and www-data.

supervisor.conf:

  • supervisord runs as root
  • nginx now runs as root instead of php-cli user
  • php-fpm now runs as root instead of php-cli user
  • logrotate entry is removed, since logs in docker are redirected to stdout / stderr
  • listener.php now runs as root, so that it can kill supervisord

.github/workflows/ci.yml:

  • Build on tags, master, as well as PRs currently
# Build
docker build -t snappymail . -f .docker/release/Dockerfile

# Run
docker run --rm -it -p 8888:8888 snappymail
# Visit at https://localhost:8888?admin. Get admin password from the created /snappymail/data/_data_/_default_/admin_password.txt

Progress

image

TODO

  • Use release .tar.gz instead of .zip
  • Add more php extensions
  • Test php extensions:
    • gnupg
    • ldap
    • pdo_mysql
    • pdo_pgsql
    • redis,
  • Harden nginx and php-fpm
  • Remove unneeded php-cli user from Dockerfile
  • Validate with mail accounts
  • Test crond invokes logrotate cron
  • Combine Dockerfile RUN statements for php extensions to a single statement
  • Test logging to stdout and stderr via supervisord
  • Slim down docker image
  • Finally, github actions to push to Docker Hub on tags (and master?), with multi-arch builds.
    • @the-djmaze Decide on architectures to build. Fewer archs will speed up builds. On Github actions currently, linux/386 and linux/amd64 builds can be as fast as a few minutes, but linux/arm64 builds can be as slow as 30 mins or more. linux/arm6 and linux/arm7 builds are about 15-20mins i think.
    • @the-djmaze this repo may be setup to run CI on PRs, either automatically or manually approved. This will be useful for future PRs to see if the docker image works.
      • Settings > Actions > General > Actions permissions, set to Allow all actions and reusable workflows
      • Settings > Actions > General > Fork pull request workflows from outside collaborators
    • @the-djmaze Secrets DOCKERHUB_USERNAME and DOCKERHUB_TOKEN must be setup in the repo's secrets. Settings > Secrets and variables > Actions > Add repository secret. I'll leave you to setup the DockerHub account
  • Readme github ci and docker hub badges
    • @the-djmaze It's just two CI badges in the readme, under the SnappyMail title
  • Usage docs and examples
    • @the-djmaze Decide on docs folder. Currently, it is ./examples. It's probably better named ./docs.
    • @leojonathanoh Change all instances of image: leojonathanoh/snappymail to image: the-djmaze/snappymail in examples
  • @leojonathanoh Delete .docker/release/files/usr/local/include/application.ini (see Enhancement: Add Docker Hub image #965 (comment))
  • @leojonathanoh Clean up all TODO: in the CI files

Implements #44

@leojonathanoh leojonathanoh mentioned this pull request Feb 15, 2023
@leojonathanoh
Copy link
Author

i'll be pushing fixes, i'll drop a note when i think it is ready

@the-djmaze
Copy link
Owner

the-djmaze commented Feb 15, 2023

Thanks for all your work so far!

Why a "zip"?
Tar has some benefits, like the right file permissions.

For example: snappymail/v/0.0.0/imapsync.php is an executable file that is similar to the imapsync perl script from https://imapsync.lamiral.info/

When using zip all that information is lost.

@leojonathanoh
Copy link
Author

Sor

Thanks for all your work so far!

Why a "zip"? Tar has some benefits, like the right file permissions.

For example: snappymail/v/0.0.0/imapsync.php is an executable file that is similar to the imapsync perl script from https://imapsync.lamiral.info/

When using zip all that information is lost.

sorry, i don't really understand, which part of the code are you referering to?

@kouinkouin
Copy link

Yeah, nice work!

Why use PHP 7.4 instead of 8.1 (or 8.2)?

Why a "zip"? Tar has some benefits, like the right file permissions.

I guess because the previous (actual) Dockerfile uses the ZIP file of Github release.
But indeed, use the tar.gz could be better.
Must have: verify signature of the release file.

Why make multiple RUN apk install instructions instead of only one RUN ?
That could avoid to have to many layers and (maybe, I didn't try) a slower image?

@leojonathanoh
Copy link
Author

leojonathanoh commented Feb 15, 2023

Why use PHP 7.4 instead of 8.1 (or 8.2)?

yeah, i thought 7.4 was the minimum so i used it. 8.1 i heard has quite a bit faster according to benchmarks :) should we use it?

I guess because the previous (actual) Dockerfile uses the ZIP file of Github release.
But indeed, use the tar.gz could be better.
Must have: verify signature of the release file.

Oh i understand now. Yes .tar should preserve file permissions better. I got the idea from #44 (comment) whose dockerfile used .zip. Didn't realise there was .tar.
.

Why make multiple RUN apk install instructions instead of only one RUN ? That could avoid to have to many layers and (maybe, I didn't try) a slower image?

Yes, i should combine them. It was the purpose of better caching while i was working on those php extensions which was quite difficult to install correctly.

@leojonathanoh
Copy link
Author

leojonathanoh commented Feb 15, 2023

I'm building it on my own fork PR leojonathanoh#1 so when it pushes you guys can try to pull it. Check https://github.com/leojonathanoh/snappymail/pull/1/checks.

Docker hub repo: https://hub.docker.com/r/leojonathanoh/snappymail

# Latest build on PR
docker run --rm -it -p 8888:8888 leojonathanoh/snappymail:merge
# Or a specific build on PR
docker run --rm -it -p 8888:8888 leojonathanoh/snappymail:merge-<sha>

@leojonathanoh
Copy link
Author

Alright, it's pushed:

docker run --rm -it -p 8888:8888 leojonathanoh/snappymail:merge

@leojonathanoh
Copy link
Author

i'll be testing with with actual email accounts.

@leojonathanoh
Copy link
Author

the image is a tad big, if anybody has any idea how to slim it down it would be nice 😄

@leojonathanoh
Copy link
Author

Just a little update, from my general testing it works nicely.

@the-djmaze
Copy link
Owner

the-djmaze commented Feb 16, 2023

Great!

You have any idea if this can be added/changed?

#873 (comment)

The request is a docker without TLS.

@leojonathanoh
Copy link
Author

#873 (comment)

Reading the discussion, I understand the #873 OP's frustration because the current docker-compose.yml uses the .docker/dev/* files, and expecially the default.conf for nginx uses ssl_* directives, such that nginx is doing 2 things (cgi proxying to php, and TLS reverse proxy). It's better to have separation of concerts, with nginx only do 1 thing which is CGI proxying, and run a separate service as the TLS termination/ loadbalancer e.g. traefik.

I suggest once the official Docker Hub image is built, to use it in the docker-compose.yml so that it no longer uses the .docker/dev/* default.conf anymore, and that snappymail simply serves HTTP on port 8888. I think it is better to not pollute the current docker-compose.yml with TLS reverse proxy example(s), so that it is kept for simple demonstration purposes of using snappymail. Instead, include a separate docker-compose.yml example with traefik (with ACME certs) and snappymail. What do you think?

@leojonathanoh
Copy link
Author

leojonathanoh commented Feb 16, 2023

I've made the docker-compose.yml now no longer use the .docker/dev/*, so that it is purely independent, and it may be moved to /docs or /docs/examples. Would that be better? Then we can add a traefik example there as well.

@leojonathanoh
Copy link
Author

Thinking again, now I understand that the /docker-compose.yml is for the purpose of setting up a development environment for snappymail. Since that's its purpose, it's probably better to leave it as it is and not change it. So I'll revert the commits making changes to it.

As for the examples for the reverse proxy, they should really go in /docs or /examples.

@leojonathanoh
Copy link
Author

Ok i got most of the docs down, the main part is to need help validating the image works for various use cases e.g. gpg mails, contact sync, redis caching, etc which i know very little about.

@leojonathanoh
Copy link
Author

leojonathanoh commented Feb 17, 2023

Just another update, i've tested OpenPGP and GnuPG, and from my testing against docker-mailserver (i should open another PR to fix the outdated `.docker/dev/*, after we are done with this PR), it seems to work nicely.

Logs:

snappymail_1  | [2023-02-17 03:42:49.978][307593d9] POST[INFO]: {"Action":"GnupgGetKeys","XToken":"dc62cc6a62450f0890254483c19cf98de6525f85"}
snappymail_1  | [2023-02-17 03:42:49.989][307593d9] JSON[INFO]: {"Action":"GnupgGetKeys","Result":{"public":[{"disabled":false,"expired":false,"revoked":false,"is_secret":false,"can_encrypt":true,"uids":[{"name":"Test user","comment":"","email":"*******@example.com","uid":"Test user <*******@example.com>","revoked":false,"invalid":false}],"subkeys":[{"fingerprint":"53...
...
snappymail_1  | [2023-02-17 03:43:16.105][c2af48c2] JSON[INFO]: Action: DoSendMessage
snappymail_1  | [2023-02-17 03:43:16.105][c2af48c2] POST[INFO]: {"identityID":"","messageFolder":"","messageUid":0,"saveFolder":"Sent","from":"*******@example.com","to":"*******2@example.com","cc":"","bcc":"","replyTo":"","subject":"******* encrypt + sign","draftInfo":null,"inReplyTo":"","references":"","markAsImportant":0,"attachments":[],"dsn":1,"requireTLS":1,"readReceiptRequest":1,"html":"","plain":"","signed":"Content-Type: multipart\/signed; micalg=\"pgp-sha256\"; protocol=\"application\/pgp-signature\"; boundary=\"part43000000000114807000\"\r\nContent-Transfer-Encoding: 7Bit\r\n\r\n--part43000000000114807000\r\nContent-Type: multipart\/alternative; boundary=\"part964030000404336522500900\"\r\n\r\n--part964030000404336522500900\r\nContent-Type: text\/plain; charset=\"utf-8\"\r\nContent-Transfer-Encoding: base64\r\n\r\ndGVzdA==\r\n--part964030000404336522500900\r\nContent-Type: text\/html; charset=\"utf-8\"\r\nContent-Transfer-Encoding: base64\r\n\r\nPGRpdj50ZXN0PGJyPjwvZGl2Pg==\r\n--part964030000404336522500900--\r\n\r\n--part43000000000114807000\r\nContent-Type: application\/pgp-signature; name=\"signature.asc\"\r\nContent-Transfer-Encoding: 7Bit\r\n\r\n-----BEGIN PGP SIGNATURE-----\r\n\r\nwsDzBAEBCgAnBQJj7vfTCRCuOelGv+\/PEBYhBFN1u0glhhNNmAiFna456Ua\/\r\n788QAADUdwv\/c2Doh\/d5G5ccRgI15s8bUAcExXwjmEcnpawfmXzB3TEGgF7H\r\nLgiYm7ideIHznCkWQ8O8iHWmX5sP1Vx1D1Hvy6ecc8\/BervcL4BcSDIvi9YL\r\nc2U8\/BMYu0jkk\/U0Kp59dYUbPLh\/tt5W62ZYZ2bqmaGwPbQkWKUj6tnH6vLE\r\nP6Rnnx8A9jzjyex98i3nwIWH6FSic8jlxpnOK6j5vbdYJn5H+x5HVz\/Rs+ov\r\nk5vmL2q0Sl4Etcn+sKnYLZy609sDtqsishGlLiZ7T6PyRSRVTSjEDHGzOSMF\r\nRC+6GZmECT0QJ2433Vp88srwkN\/4Sl4QwnzlYpa6qFf8l0jHDInjwMkg1LS1\r\nEpwixw3B34t1exIbuTLvuPlJLGgXEiGPkHJNG+aPJef+som8G6XJJ4JPp0al\r\n3mqBp2v7o0AqmulHE3vq24ZxXkuHAMUyD7RrGq2o8faXcsrtQD3XDeK5QXGV\r\nboBkX6Vjc1+J7cdepnh21NnTUDqYu3zkHfeMpRBm3n87\r\n=Eor8\r\n-----END PGP SIGNATURE-----\r\n\r\n--part43000000000114807000--\r\n","boundary":"part43000000000114807000","Action":"SendMessage","XToken":"dc62cc6a62450f0890254483c19cf98de6525f85"}
snappymail_1  | [2023-02-17 03:43:16.106][c2af48c2] IMAP[INFO]: Start connection to "ssl://example.com:993"
...
snappymail_1  | [2023-02-17 03:43:16.182][c2af48c2] JSON[INFO]: {"Action":"SendMessage","Result":true,"epoch":1676605396}

and screenshot:

image image image
docker exec -it snappymail_snappymail_1 sh
/snappymail # find data/_data_/_default_/storage/
data/_data_/_default_/storage/
data/_data_/_default_/storage/example.com
data/_data_/_default_/storage/example.com/test
data/_data_/_default_/storage/example.com/test/settings_local
data/_data_/_default_/storage/example.com/test/additionalaccounts
data/_data_/_default_/storage/example.com/test/.sessions
data/_data_/_default_/storage/example.com/test/.sessions/cbe0274095a8c8f723aa2085e7a41b0e6172d3f4
data/_data_/_default_/storage/example.com/test/test2@example.com
data/_data_/_default_/storage/example.com/test/test2@example.com/settings_local
data/_data_/_default_/storage/example.com/test/test2@example.com/.files
data/_data_/_default_/storage/example.com/test/settings
data/_data_/_default_/storage/example.com/test/.gnupg
data/_data_/_default_/storage/example.com/test/.gnupg/S.gpg-agent.extra
data/_data_/_default_/storage/example.com/test/.gnupg/S.gpg-agent.browser
data/_data_/_default_/storage/example.com/test/.gnupg/trustdb.gpg
data/_data_/_default_/storage/example.com/test/.gnupg/private-keys-v1.d
data/_data_/_default_/storage/example.com/test/.gnupg/private-keys-v1.d/06B35D350E7397EC7499654530AB199EA829B3DC.key
data/_data_/_default_/storage/example.com/test/.gnupg/private-keys-v1.d/14DCEF524494613F82AAE2B3A870F89A0BF58368.key
data/_data_/_default_/storage/example.com/test/.gnupg/pubring.kbx
data/_data_/_default_/storage/example.com/test/.gnupg/S.gpg-agent
data/_data_/_default_/storage/example.com/test/.gnupg/S.gpg-agent.ssh
data/_data_/_default_/storage/example.com/test/.gnupg/pubring.kbx~
data/_data_/_default_/storage/__nobody__
data/_data_/_default_/storage/__nobody__/ec413e4e05ad76a7fd317512654eedb68a7df1db

So i'm left with testing contact sync, with / without redis.

@leojonathanoh
Copy link
Author

leojonathanoh commented Feb 17, 2023

files caching is working:

$ docker exec -it snappymail_snappymail_1 sh
/snappymail # find data/_data_/_default_/cache/
data/_data_/_default_/cache/
data/_data_/_default_/cache/12
data/_data_/_default_/cache/12/0b
data/_data_/_default_/cache/12/0b/120b55b67752efb65c201664b25616fc09135f93
data/_data_/_default_/cache/23
data/_data_/_default_/cache/23/40
data/_data_/_default_/cache/23/40/2340061528ca14617684455305e76a4d20e8f251
data/_data_/_default_/cache/__
data/_data_/_default_/cache/__/te
data/_data_/_default_/cache/__/te/st
data/_data_/_default_/cache/__/te/st/test_example_com
data/_data_/_default_/cache/__/te/st/test_example_com/3e
data/_data_/_default_/cache/__/te/st/test_example_com/3e/24
data/_data_/_default_/cache/__/te/st/test_example_com/3e/24/3e24e6cf1fbe02b29f62df3a36bd437db9d630c4
data/_data_/_default_/cache/__/te/st/test_example_com/b6
data/_data_/_default_/cache/__/te/st/test_example_com/b6/0e
data/_data_/_default_/cache/__/te/st/test_example_com/b6/0e/b60e5eda410288314d6561b3573f92d48766030b
data/_data_/_default_/cache/__/te/st/test_example_com/b1
data/_data_/_default_/cache/__/te/st/test_example_com/b1/ec
data/_data_/_default_/cache/__/te/st/test_example_com/b1/ec/b1eca70046629cf090ff7baf6cd25d7ec2aec4b4
data/_data_/_default_/cache/__/te/st/test_example_com/e2
data/_data_/_default_/cache/__/te/st/test_example_com/e2/d4
data/_data_/_default_/cache/__/te/st/test_example_com/e2/d4/e2d44ccc3d72ae59fe8948e7aa957d8effbe5aa1
data/_data_/_default_/cache/__/te/st/test_example_com/32
data/_data_/_default_/cache/__/te/st/test_example_com/32/51
data/_data_/_default_/cache/__/te/st/test_example_com/32/51/325117d14e6c7b17d7f1afda5217ee16e831eaa7
data/_data_/_default_/cache/1d
data/_data_/_default_/cache/1d/23
data/_data_/_default_/cache/1d/23/1d232a7a0c458c0d3fa9945af5900f65a5f517c7

redis caching is also working:

$ docker exec -it snappymail_redis_1 sh
/data # redis-cli 
127.0.0.1:6379> scan 0
1) "0"
2) 1) "test_example_com/3e24e6cf1fbe02b29f62df3a36bd437db9d630c4"
   2) "test_example_com/b1eca70046629cf090ff7baf6cd25d7ec2aec4b4"
   3) "test_example_com/e2d44ccc3d72ae59fe8948e7aa957d8effbe5aa1"
   4) "test_example_com/b60e5eda410288314d6561b3573f92d48766030b"
   5) "test_example_com/325117d14e6c7b17d7f1afda5217ee16e831eaa7"
   6) "120b55b67752efb65c201664b25616fc09135f93"
127.0.0.1:6379> get test_example_com/3e24e6cf1fbe02b29f62df3a36bd437db9d630c4
"{\"FolderHash\":\"9406bb65b795965f80f471315cc36c0b\",\"Uids\":[3,1]}"
127.0.0.1:6379> get test_example_com/b1eca70046629cf090ff7baf6cd25d7ec2aec4b4
"{\"FolderHash\":\"39825f5db43ada4d7f1b8941e66f7224\",\"Uids\":[5,4,3,2,1]}"
127.0.0.1:6379> get test_example_com/e2d44ccc3d72ae59fe8948e7aa957d8effbe5aa1
"{\"FolderHash\":\"d39d2a1d4cd45660bbb9bd11cccab931\",\"Uids\":[11,10,9,8,6,7,5,4,3,2,1]}"
127.0.0.1:6379> get test_example_com/b60e5eda410288314d6561b3573f92d48766030b
"{\"FolderHash\":\"69ac669d3ef5861a95c27a178c862f88\",\"Uids\":[3,2,1]}"
127.0.0.1:6379> get 120b55b67752efb65c201664b25616fc09135f93

with these config options:

  • cache > enable: yes
  • cache > fast_cache_driver: redis
  • labs > fast_cache_redis_host: redis
  • labs > fast_cache_redis_port: 6379

@leojonathanoh
Copy link
Author

leojonathanoh commented Feb 17, 2023

mysql and postgres drivers seem to be working nicely for contact sync:

Admin Panel > Contacts:
image

mysql:

$ docker exec -it snappymail_db_1 sh
sh-4.2# mysql
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
sh-4.2# mysql -uroot -proot
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 13
Server version: 5.7.41 MySQL Community Server (GPL)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| snappymail         |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> use snappymail;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+------------------------+
| Tables_in_snappymail   |
+------------------------+
| rainloop_ab_contacts   |
| rainloop_ab_properties |
| rainloop_system        |
| rainloop_users         |
+------------------------+
4 rows in set (0.00 sec)

mysql> select * from rainloop_users;
+---------+------------------+
| id_user | rl_email         |
+---------+------------------+
|       1 | test@example.com |
+---------+------------------+
1 row in set (0.00 sec)

mysql> select * from rainloop_ab_contacts;
+------------+----------------------------------------------------+---------+-------------------+------------+---------+------+
| id_contact | id_contact_str                                     | id_user | display           | changed    | deleted | etag |
+------------+----------------------------------------------------+---------+-------------------+------------+---------+------+
|          1 | sabre-vobject-c66f2582-2947-46c6-bf96-673689e5180f |       1 | test2@example.com | 1676608880 |       0 |      |
|          2 | sabre-vobject-7c484cfa-a510-4b0d-af2d-ea6e3c21085c |       1 | test@example.com  | 1676608905 |       0 |      |
+------------+----------------------------------------------------+---------+-------------------+------------+---------+------+
2 rows in set (0.00 sec)

mysql> 

postgres:

image
$ docker exec -it snappymail_db_1 sh
/ # psql -U snappymail

snappymail=# \d
                          List of relations
 Schema |                Name                 |   Type   |   Owner    
--------+-------------------------------------+----------+------------
 public | id_user                             | sequence | snappymail
 public | rainloop_ab_contacts                | table    | snappymail
 public | rainloop_ab_contacts_id_contact_seq | sequence | snappymail
 public | rainloop_ab_properties              | table    | snappymail
 public | rainloop_ab_properties_id_prop_seq  | sequence | snappymail
 public | rainloop_system                     | table    | snappymail
 public | rainloop_users                      | table    | snappymail
(7 rows)

snappymail=# select * from id_user;
 last_value | log_cnt | is_called 
------------+---------+-----------
          1 |      32 | t
(1 row)

snappymail=# select * from rainloop_users;
 id_user |     rl_email     
---------+------------------
       1 | test@example.com
(1 row)

snappymail=# sleect * from rainloop_ab_contacts;
ERROR:  syntax error at or near "sleect"
LINE 1: sleect * from rainloop_ab_contacts;
        ^
snappymail=# select * from rainloop_ab_contacts;
 id_contact |                   id_contact_str                   | id_user |      display      |  changed   | deleted | etag 
------------+----------------------------------------------------+---------+-------------------+------------+---------+------
          1 | sabre-vobject-7fa8b8df-7296-4283-a13a-9db907edb204 |       1 | test@example.com  | 1676609195 |       0 | 
          2 | sabre-vobject-7e01b980-ae43-4eb4-8bcf-b64b289e2d9c |       1 | test2@example.com | 1676609208 |       0 | 
(2 rows)

snappymail=# 

Settings > Contacts:

image

Contacts:

image

@leojonathanoh
Copy link
Author

I'm left wit hardening checks.

@leojonathanoh
Copy link
Author

leojonathanoh commented Feb 17, 2023

ACLs lgtm:

/snappymail/snappymail/v/2.26.1 # ls -al /
total 96
drwxr-xr-x    1 root     root          4096 Feb 17 06:25 .
drwxr-xr-x    1 root     root          4096 Feb 17 06:25 ..
-rwxr-xr-x    1 root     root             0 Feb 17 06:25 .dockerenv
drwxr-xr-x    1 root     root          4096 Feb 15 13:10 bin
drwxr-xr-x    5 root     root           340 Feb 17 06:25 dev
-rwxr-xr-x    1 root     root          2923 Feb 17 05:27 entrypoint.sh
drwxr-xr-x    1 root     root          4096 Feb 17 06:25 etc
drwxr-xr-x    1 root     root          4096 Feb 11 10:17 home
drwxr-xr-x    1 root     root          4096 Feb 16 06:09 lib
-rw-r--r--    1 root     root           519 Feb 15 03:03 listener.php
-rwxr-xr-x    1 root     root          3129 Feb 15 07:48 logrotate-loop.sh
drwxr-xr-x    5 root     root          4096 Feb 10 16:45 media
drwxr-xr-x    2 root     root          4096 Feb 10 16:45 mnt
drwxr-xr-x    2 root     root          4096 Feb 10 16:45 opt
dr-xr-xr-x 1304 root     root             0 Feb 17 06:25 proc
drwx------    1 root     root          4096 Feb 17 06:26 root
drwxr-xr-x    1 root     root          4096 Feb 17 06:25 run
drwxr-xr-x    2 root     root          4096 Feb 10 16:45 sbin
drwxr-xr-x    4 www-data www-data      4096 Feb 17 05:31 snappymail
drwxr-xr-x    2 root     root          4096 Feb 10 16:45 srv
-rw-r--r--    1 root     root          1456 Feb 17 06:01 supervisor.conf
dr-xr-xr-x   13 root     root             0 Feb 17 06:25 sys
drwxrwxrwt    1 root     root          4096 Feb 17 06:32 tmp
drwxr-xr-x    1 root     root          4096 Feb 15 03:03 usr
drwxr-xr-x    1 root     root          4096 Feb 16 06:09 var
/snappymail # ls -al
total 44
drwxr-xr-x    4 www-data www-data      4096 Feb 17 05:31 .
drwxr-xr-x    1 root     root          4096 Feb 17 06:25 ..
-r--r-----    1 www-data www-data      1618 Feb 17 05:31 .htaccess
-r--r-----    1 www-data www-data      9318 Feb 17 05:31 README.md
-r--r-----    1 www-data www-data       828 Feb 17 05:31 _include.php
drwx------    3 www-data www-data      4096 Feb 16 07:18 data
-r--r-----    1 www-data www-data       594 Feb 17 05:31 index.php
-r--r-----    1 www-data www-data       285 Feb 17 05:31 serviceworker.js
dr-xr-x---    3 www-data www-data      4096 Feb 17 05:31 snappymail
/snappymail # cd data/
/snappymail/data # ls -al
total 40
drwx------    3 www-data www-data      4096 Feb 16 07:18 .
drwxr-xr-x    4 www-data www-data      4096 Feb 17 05:31 ..
-rw-r-----    1 www-data www-data        19 Feb 16 03:18 .htaccess
-rw-------    1 www-data www-data         6 Feb 16 07:18 INSTALLED
-rw-r-----    1 www-data www-data       121 Feb 16 03:18 README.md
-rw-------    1 www-data www-data       104 Feb 16 07:18 SALT.php
-rw-r-----    1 www-data www-data         6 Feb 16 03:18 VERSION
drwxr-xr-x    3 www-data www-data      4096 Feb 16 07:18 _data_
-rw-------    1 www-data www-data         9 Feb 16 07:18 index.html
-rw-------    1 www-data www-data         9 Feb 16 07:18 index.php
/snappymail/data # cd _data_/
/snappymail/data/_data_ # ls -al
total 12
drwxr-xr-x    3 www-data www-data      4096 Feb 16 07:18 .
drwx------    3 www-data www-data      4096 Feb 16 07:18 ..
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 _default_
/snappymail/data/_data_ # cd _default_/
/snappymail/data/_data_/_default_ # ls -al
total 80
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 .
drwxr-xr-x    3 www-data www-data      4096 Feb 16 07:18 ..
-rw-------    1 www-data www-data     40960 Feb 17 04:39 AddressBook.sqlite
-rw-------    1 www-data www-data        13 Feb 16 07:18 admin_password.txt
drwx------    6 www-data www-data      4096 Feb 17 03:08 cache
drwxr-xr-x    2 www-data www-data      4096 Feb 17 06:25 configs
drwx------    2 www-data www-data      4096 Feb 17 05:36 domains
drwxr-xr-x    2 www-data www-data      4096 Feb 17 06:25 logs
drwx------    2 www-data www-data      4096 Feb 16 07:18 plugins
drwx------    4 www-data www-data      4096 Feb 17 03:09 storage
/snappymail/data/_data_/_default_ # ls -al *
-rw-------    1 www-data www-data     40960 Feb 17 04:39 AddressBook.sqlite
-rw-------    1 www-data www-data        13 Feb 16 07:18 admin_password.txt

cache:
total 24
drwx------    6 www-data www-data      4096 Feb 17 03:08 .
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 ..
drwx------    3 www-data www-data      4096 Feb 16 08:10 12
drwx------    3 www-data www-data      4096 Feb 16 07:18 1d
drwx------    3 www-data www-data      4096 Feb 16 07:18 23
drwx------    3 www-data www-data      4096 Feb 17 03:08 __

configs:
total 20
drwxr-xr-x    2 www-data www-data      4096 Feb 17 06:25 .
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 ..
-rw-------    1 www-data www-data      8631 Feb 17 06:27 application.ini

domains:
total 28
drwx------    2 www-data www-data      4096 Feb 17 05:36 .
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 ..
-rw-------    1 www-data www-data      2247 Feb 16 07:18 d4f6713258d6.json
-rw-------    1 www-data www-data      2250 Feb 16 07:18 default.json
-rw-------    1 www-data www-data        50 Feb 16 07:18 disabled
-rw-------    1 www-data www-data      2245 Feb 17 03:08 example.com.json
-rw-------    1 www-data www-data      2248 Feb 17 05:36 example2.com.json

logs:
total 116
drwxr-xr-x    2 www-data www-data      4096 Feb 17 06:25 .
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 ..
-rw-r--r--    1 www-data www-data         0 Feb 17 06:25 auth.log
-rw-r--r--    1 www-data www-data    109435 Feb 17 06:32 errors.log

plugins:
total 8
drwx------    2 www-data www-data      4096 Feb 16 07:18 .
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 ..

storage:
total 16
drwx------    4 www-data www-data      4096 Feb 17 03:09 .
drwxr-xr-x    8 www-data www-data      4096 Feb 17 04:39 ..
drwx------    2 www-data www-data      4096 Feb 17 03:09 __nobody__
drwx------    3 www-data www-data      4096 Feb 17 03:08 example.com
/snappymail/data/_data_/_default_ # cd /snappymail/snappymail/
/snappymail/snappymail # ls -al
total 12
dr-xr-x---    3 www-data www-data      4096 Feb 17 05:31 .
drwxr-xr-x    4 www-data www-data      4096 Feb 17 05:31 ..
dr-xr-x---    3 www-data www-data      4096 Feb 17 05:31 v
/snappymail/snappymail # cd v/
/snappymail/snappymail/v # ls -al
total 12
dr-xr-x---    3 www-data www-data      4096 Feb 17 05:31 .
dr-xr-x---    3 www-data www-data      4096 Feb 17 05:31 ..
dr-xr-x---    5 www-data www-data      4096 Feb 17 05:31 2.26.1
/snappymail/snappymail/v # cd 2.26.1/
/snappymail/snappymail/v/2.26.1 # ls -al
total 48
dr-xr-x---    5 www-data www-data      4096 Feb 17 05:31 .
dr-xr-x---    3 www-data www-data      4096 Feb 17 05:31 ..
dr-xr-x---    6 www-data www-data      4096 Feb 17 05:31 app
-r--r-----    1 www-data www-data      1202 Feb 17 05:31 cpanel.php
-r--r-----    1 www-data www-data      6765 Feb 17 05:31 imapsync.php
-r--r-----    1 www-data www-data      6056 Feb 17 05:31 include.php
-r--r-----    1 www-data www-data         0 Feb 17 05:31 index.php
-r--r-----    1 www-data www-data      5214 Feb 17 05:31 setup.php
dr-xr-x---    6 www-data www-data      4096 Feb 17 05:31 static
dr-xr-x---   21 www-data www-data      4096 Feb 17 05:31 themes
/snappymail/snappymail/v/2.26.1 # 

@leojonathanoh
Copy link
Author

I don't think we should combine the RUN statements of each php extension, for better docker caching whenever the dockerfile is updated. More layers doesn't affect performance with the overlay2 driver that most use already, see https://docs.docker.com/storage/storagedriver/overlayfs-driver/#overlayfs-and-docker-performance. If that's all fine, the image is good to go.

What's left is where the example docker-compose.yml should go, e.g. /examples or /docs/examples, or in the repo's wiki (where most of the docs are)? I hope my examples are clear.

@the-djmaze
Copy link
Owner

the-djmaze commented Feb 17, 2023

Why is snappymail in root and not in something like /var/www/snappymail?

Also the data directory should be best outside public www for security.
If PHP runs as www-data and nginx is used, everyrhing can be accessed by malicious visitors

@Leopere
Copy link

Leopere commented Nov 15, 2023

No, no just in the final version would be great.

Honestly I'd just be elated if this would get merged already.

@Orhideous
Copy link

Honestly I'd just be elated if this would get merged already.

Same thing. Can't wait to finally migrate from old rainloop image.

@the-djmaze the-djmaze merged commit 24dbff9 into the-djmaze:master Nov 20, 2023
@the-djmaze
Copy link
Owner

the-djmaze commented Nov 21, 2023

https://hub.docker.com/r/djmaze/snappymail

@tombii
Copy link

tombii commented Nov 21, 2023

Awesome :) Now we're just waiting for the arm64 version as well so it can run in Oracle cloud :)

@Leopere
Copy link

Leopere commented Nov 21, 2023

thank you ever so very much I'm going to try to schedule a talk about this with a local tech meeting group because I think this might be a turning point for usability of GPG

@leojonathanoh
Copy link
Author

Thank you for merging this 😄 Should another PR be opened for other archs? There were a few things left to do ... ?

the-djmaze pushed a commit that referenced this pull request Nov 21, 2023
@the-djmaze
Copy link
Owner

the-djmaze commented Nov 21, 2023

Thank you for merging this 😄 Should another PR be opened for other archs? There were a few things left to do ... ?

I had to modify a few things to get it all up and running.
As you can see in the commit history at
https://github.com/the-djmaze/snappymail/commits/master/.github/workflows/docker.yml

I do still have 1 main concern: persistent storage
What happens with all user setups, domains, etc. when the image is removed or replaced?
Do users still have their settings and the ?admin still the right configuration and installed extensions?
https://docs.docker.com/storage/
https://towardsai.net/p/l/a-guide-to-persistent-storage-in-docker

If everything works, we can do more archs but i think some things are missing, like PHP:

  • uuid
  • gmagick or imagick
  • iconv
  • sodium
  • sqlite
  • exif
  • finfo
  • cURL
  • OpenSSL

So check the ?admin#/about page for improvements
Then anyone can open a new issue for them 😉

@leojonathanoh
Copy link
Author

Persistent storage is stored as a docker volume that the user should mount at /var/lib/snappymail, which I assume stores all snappymail state? So long as the user remounts the same volume at /var/lib/snappymail, everything should be preserved.

About those extensions, I suppose you want all in that list to be included in the image? Shouldn't be too difficult, there's a good reference here.

Thanks for all your work 😃

@hibobmaster
Copy link

This pr breaks arm build. With 4daaa37 i can successfully build snappymail on my arm64 device via

git pull
cd .docker/release
wget https://github.com/the-djmaze/snappymail/releases/download/v2.29.2/snappymail-2.29.2.zip
docker build -t snappymail:2.29.2 -t snappymail:latest . --build-arg FILES_ZIP=snappymail-2.29.2.zip

After this pr, i build snappymail with docker build -t csuwf/snappymail:2.29.4 -t csuwf/snappymail:latest . and get following errors

log
❯ docker build -t csuwf/snappymail:2.29.4 -t csuwf/snappymail:latest .
[+] Building 1.0s (32/34)                                                                               docker:default
 => [internal] load .dockerignore                                                                                 0.0s
 => => transferring context: 2B                                                                                   0.0s
 => [internal] load build definition from Dockerfile                                                              0.0s
 => => transferring dockerfile: 4.38kB                                                                            0.0s
 => resolve image config for docker.io/docker/dockerfile:1                                                        0.4s
 => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f5  0.0s
 => [internal] load metadata for docker.io/library/php:8.1-fpm-alpine                                             0.4s
 => [internal] load metadata for docker.io/library/alpine:3.15                                                    0.4s
 => CANCELED [builder  1/11] FROM docker.io/library/alpine:3.15@sha256:794bc829ea39d85926be70fedfc9fb17aa4244d82  0.1s
 => => resolve docker.io/library/alpine:3.15@sha256:794bc829ea39d85926be70fedfc9fb17aa4244d82b2fbecb5634b03e5dd9  0.0s
 => => sha256:794bc829ea39d85926be70fedfc9fb17aa4244d82b2fbecb5634b03e5dd97aca 1.64kB / 1.64kB                    0.0s
 => => sha256:8f8290f2db95621a871194953474a0cb610d40e1490c29669110f7a68d15fe55 528B / 528B                        0.0s
 => [internal] load build context                                                                                 0.0s
 => => transferring context: 716B                                                                                 0.0s
 => CANCELED [final  1/16] FROM docker.io/library/php:8.1-fpm-alpine@sha256:de0006508154945664607803a2345bd8bb33  0.1s
 => => resolve docker.io/library/php:8.1-fpm-alpine@sha256:de0006508154945664607803a2345bd8bb33fa94575e0970fe7c5  0.0s
 => => sha256:de0006508154945664607803a2345bd8bb33fa94575e0970fe7c524c7464c247 1.65kB / 1.65kB                    0.0s
 => => sha256:a8cd1d532714ab673f5bc1aa509d615eebd43d9f30f78f4ce426aeecf13d4b84 2.41kB / 2.41kB                    0.0s
 => CACHED [final  2/16] RUN apk add --no-cache ca-certificates nginx supervisor bash                             0.0s
 => CACHED [final  3/16] RUN set -eux;     apk add --no-cache freetype libjpeg-turbo libpng;     apk add --no-ca  0.0s
 => CACHED [final  4/16] RUN set -eux;     apk add --no-cache gnupg gpgme;     apk add --no-cache --virtual .dep  0.0s
 => CACHED [final  5/16] RUN set -eux;     apk add --no-cache icu-libs;     apk add --no-cache --virtual .deps i  0.0s
 => CACHED [final  6/16] RUN set -eux;     apk add --no-cache libldap;     apk add --no-cache --virtual .deps op  0.0s
 => CACHED [final  7/16] RUN docker-php-ext-install pdo_mysql                                                     0.0s
 => CACHED [final  8/16] RUN docker-php-ext-install opcache                                                       0.0s
 => CACHED [final  9/16] RUN set -eux;     apk add --no-cache postgresql-libs;     apk add --no-cache --virtual   0.0s
 => CACHED [final 10/16] RUN set -eux;     apk add --no-cache liblzf zstd-libs;     apk add --no-cache --virtual  0.0s
 => CACHED [final 11/16] RUN set -eux;     apk add --no-cache libzip;     apk add --no-cache --virtual .deps lib  0.0s
 => CACHED [builder  2/11] RUN apk add --no-cache php7 php7-json php-phar php-zip                                 0.0s
 => CACHED [builder  3/11] RUN apk add --no-cache npm                                                             0.0s
 => CACHED [builder  4/11] RUN npm install -g gulp yarn                                                           0.0s
 => CACHED [builder  5/11] WORKDIR /source                                                                        0.0s
 => ERROR [builder  6/11] COPY package.json yarn.lock ./                                                          0.0s
 => CACHED [builder  7/11] RUN yarn install                                                                       0.0s
 => CACHED [builder  8/11] COPY . .                                                                               0.0s
 => CACHED [builder  9/11] RUN sed -i 's_^if.*rename.*snappymail.v.0.0.0.*$_if (!!system("mv snappymail/v/0.0.0   0.0s
 => CACHED [builder 10/11] RUN php release.php                                                                    0.0s
 => CACHED [builder 11/11] RUN set -eux;     VERSION=$( ls build/dist/releases/webmail );     ls -al build/dist/  0.0s
 => CACHED [final 12/16] COPY --chown=www-data:www-data --from=builder /snappymail /snappymail                    0.0s
 => CACHED [final 13/16] RUN mv -v /snappymail/data /var/lib/snappymail;                                          0.0s
 => ERROR [final 14/16] COPY --chown=root:root .docker/release/files /                                            0.0s
------
 > [builder  6/11] COPY package.json yarn.lock ./:
------
------
 > [final 14/16] COPY --chown=root:root .docker/release/files /:
------
Dockerfile:100
--------------------
  98 |     RUN mv -v /snappymail/data /var/lib/snappymail;
  99 |     # Setup configs
 100 | >>> COPY --chown=root:root .docker/release/files /
 101 |     RUN set -eux; \
 102 |         chown www-data:www-data /snappymail/include.php; \
--------------------
ERROR: failed to solve: failed to compute cache key: failed to calculate checksum of ref aa8b47d7-edd9-4686-81ab-847bdf41fa28::ioozf0s2ld5tkmuja5fxoya48: "/.docker/release/files": not found

@leojonathanoh
Copy link
Author

@hibobmaster please try my arm64 image in #1321. This PR didn't break arm builds.

@hibobmaster
Copy link

@leojonathanoh Sorry for my late response. I successfully build arm image after digging into the action file, the build cmd is docker build -t snappymail:latest -f .docker/release/Dockerfile . running from the root of this repository.
Thank you for your great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docker enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants