This awesome repo of mail server would be in the Mailserver Docker's Hall of Fame as it works like a charm in just 30 minutes of configuration. I've installed RainLoop and managed to send/receive mails. Some additional features such as DKIM, SPF, LE's SSL, etc. are also easy to install with detail documentation.
But I wonder if we could improve the setup.sh email update <email> <password> which is usually used by sysadmin to change one's password by using another version of this feature. Something like
$ setup.sh email update <email>
$ Enter password: <dotted/censored cursor>
just like the password prompt of any linux distro sudo password prompt.
But I think this is not really a big improvement since users have to contact directly the sysadmin and change password directly on the terminal of that sysadmin. Things will become harder if the sysadmin is on his/her vacation.
I don't think I have better idea for this changing password feature. But btw, anyone knows about which RainLoop's package can be used with this repo to let users change their password ?
I don't use Rainloop but I know that some users wanted to have a look to it few months ago.
Yes, allowing users to change their password, is an important requirement for me too. This is probably the reason why most people prefer to have a (simple) database to handle email accounts, at least for me.
@xamanu : I don't think that (simple) database is more ideal than flat files that we're using here in this repo. I think that some web mail clients by extensions are able to change users password which are stored in the linux files system.
Anyway, I don't have much experience about those web mail client extensions.
@xamanu perhaps using LDAP (built-in option in this image) may help you.
hi all, any new ideas on this? would be a huge improvement for my use case and I suspect many others
Some time has passed, any ideas on how to solve it?
We planned to use this repo as a mail server of the company but this missing feature (or future enhancement) is always on the top of the list of deploying prerequisites.
I understand, but there is nu functionality for dovecot or postfix to change the password trough these applications.
The webmail application should talk to the backend of your password storage. If this is ldap it should talk to your ldap account and change the credentials.
What options does Rainloop provide to changing passwords?
Anyone knows how to solve this issue?
I have created a pull-request, but please don't merge it. It is just to show a possible solution.
postfix-accounts.cf-file, which is writable only by root. So within the container, there should be a small library that is run as root and that can only perform the desired action. I decided to create a shell-script updatemailuser-secure which takes the arguments username, old-password and new-password. It performs a check of the old-password and than sets the new one. This script can securely be run by any user, because the old password is needed to set the new one.-script would need thes-bit to be set to run asroot`, but this is not possible for scripts. That's why, I have installed sudo and configured it to allow the server-user to run it as root.I have set this up in another docker-image (derived from `docker-mailserver' and I was able to post the following to change the password in my local test-container)
POST http://localhost:5001/change-password
{
"oldPassword": "abcde",
"newPassword": "abc",
"user": "[email protected]"
}
I would rather not have such a combination of bash-python and sudo in this solution. And there may be something much simpler. There probably are dangerous concurrency conflicts if multiple users change their passwords at the same time. On the other hand, I think starting a flask-server like this can only handle one request at a time, so concurrency is probably not an issue (but denial-of-service is).
Thinking about it, there should probably be a daemon that manages the configuration in a multi-threaded manner.
@nknapp It is in the good direction.
To avoid concurrency you could require a lock on the file and release it when its done. The "other" request could keep waiting for the lock to release. The action would not take very long.
The root permissions is a security risk indeed. You could add the new user to the postfix group and add the files to the group as well, but proper input validation needs to be done because you are doing to pass the input "username" and "password" into a shell command line and this can be potentially dangerous. I personally have no python skills.
I added a delay to the server in case the old-password was incorrect, in order to avoid brute-force attacks. But this also means that the brute-force automatically becomes a DoS.
I am also not sure, if the rainloop-plugin can send the old password with the requests (or ask for it). I haven't really looked into that yet.
It's a good idea to run the script as another user and change the file ownership.
I think, if I was going to write a service for managing these files, I would use nexe to compile a nodejs-program to a single executable. The executable seems to be larger (35M) for a simple hello world), but it is just this file and does not require any dependencies.
Another possibility would be to run the service in its own docker-container and only mount the configuration volume into that container. I think this would be the cleanest solution.
I'm starting a project for a nodejs docker-mailserver management service that can be run in a different docker container with mounted configuration volume. Have a look here.
Let me know if you want to get involved.
@nknapp good initiative, a separate docker would be better indeed. When you need input let me know.
I have created a project. Documentation is still lacking, and I have not tested it in real life yet, but this could work: Use the docker-compose file from the README, but with the new service added:
version: '2'
services:
mail:
image: tvial/docker-mailserver:latest
hostname: mail
domainname: domain.com
container_name: mail
ports:
- "25:25"
- "143:143"
- "587:587"
- "993:993"
volumes:
- maildata:/var/mail
- mailstate:/var/mail-state
- ./config/:/tmp/docker-mailserver/
environment:
- ENABLE_SPAMASSASSIN=1
- ENABLE_CLAMAV=1
- ENABLE_FAIL2BAN=1
- ENABLE_POSTGREY=1
- ONE_DIR=1
- DMS_DEBUG=0
cap_add:
- NET_ADMIN
- SYS_PTRACE
management:
image: knappmeier/docker-mailserver-management
volumes:
- ./config/:/tmp/docker-mailserver/
ports:
- 3000:3000
restart: always
volumes:
maildata:
driver: local
mailstate:
driver: local
Execute a http-request (@ must be url-encoded)
POST http://localhost:3000/users/username%40example.com
{
"oldPassword": "l33tx",
"newPassword": "s0Meth1ng-3ls3"
}
This should set the new password as long as the old one matches.
From a quick look into rainloop it as a lovely interface but it lacks on security best practices:
12345 for the admin user on installation, thus open to be hacked by automated scripts until is changed.This is only from a brief and quick view into the project documentation, that shows that is not secure by design, thus wondering what more can be found by digging into the code.
I went with roundcube in my Installation. It should be possible to write a plugin for that as well, but I soon noticed that I was unable to develop in PHP like I would in JavaScript (test first etc.). It's pretty long ago, my PHP. So I postponed this issue when I noticed, I could just use the old password hashes from my etc/shadow in the docker mailserver accounts
Great docker image, been using for a while now and it is working great. I am hosing it alongside of nextcloud and want to make the users to have mail and nextcloud account working with same login. Setting up LDAP seemed like an extreme way to go, so I thought about making a Nextcloud hook for the change password.
Do any of the proposed solution working yet? Is #828 going to be the official methods?
@joewashear007 yes it will. Waiting for the contributor to add tests and then it will be merged.
Anything happening on this? Does this actually work? Why was this never merged?
This project was stalled for some time with very low activity. That may be one explanation. Plus the PR has waited for contributor action for quite some time, perhaps the author has moved on.
Personally I don't fancy running a web server in the mail container, so I would prefer deploying it as a stand-alone docker image. Either provided in this repo or elsewhere. If it should go in this repo and be maintained here we need tests. In other words the PR is not ready to be merged, but could form the basis for an external solution (other repo referenced from readme) or could be added here with minor changes plus tests.
That is a good snippet to modify LDAP passwords
Although LDAP is a good choice, I still think that would be good to have a docker-compose sample version for MySQL driver, would help to integrate with lots of systems and frameworks.
The mission statement for this project says "only configuration files, no SQL database". If you want a database you'll probably be better served by a project that includes it out of the box and where it is the primary focus.
It shouldn't be very difficult to call the setup script to make the change with files either similar to the LDAP script, the real problem is that we have no user interface. We don't have a web server in the stack and as far as I know there is nothing in the mail protocols that support this. We could add an example with a separate web server and a very simple page for small installations, perhaps. Large installations probably use LDAP and have something in place already.
This issue was closed due to one or more of the following reasons:
If you think this happened by accident, or feel like this issue was not actually resolved, please feel free to re-open it. If there is an issue you could resolve in the meantime, please open a PR based on the current master branch so we can review it.
Most helpful comment
I have created a project. Documentation is still lacking, and I have not tested it in real life yet, but this could work: Use the docker-compose file from the README, but with the new service added:
Execute a http-request (@ must be url-encoded)
This should set the new password as long as the old one matches.