Merge branch 'setup-guide-next' into 'master'
docs/setup-{guide,example}: refresh the whole guide
See merge request simple-nixos-mailserver/nixos-mailserver!488
This commit is contained in:
+14
-5
@@ -5,10 +5,15 @@
|
||||
{
|
||||
imports = [
|
||||
(builtins.fetchTarball {
|
||||
# Pick a release version you are interested in and set its hash, e.g.
|
||||
# This is a quick and dirty way to import a NixOS mailserver release. What
|
||||
# you should do long-term is use a proper dependency pinning tool like npins
|
||||
# or flakes.
|
||||
|
||||
# URL to the tarball for the release matching your NixOS release
|
||||
url = "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/nixos-25.11/nixos-mailserver-nixos-25.11.tar.gz";
|
||||
# To get the sha256 of the nixos-mailserver tarball, we can use the nix-prefetch-url command:
|
||||
# release="nixos-25.11"; nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
|
||||
|
||||
# Hash of the unpacked tarball, run the following command to retrieve it
|
||||
# release="nixos-25.11" nix-prefetch-url "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/archive/${release}/nixos-mailserver-${release}.tar.gz" --unpack
|
||||
sha256 = "0000000000000000000000000000000000000000000000000000";
|
||||
})
|
||||
];
|
||||
@@ -30,18 +35,22 @@
|
||||
fqdn = "mail.example.com";
|
||||
domains = [ "example.com" ];
|
||||
|
||||
# reference an existing ACME configuration
|
||||
# Reference the existing ACME configuration created by nginx
|
||||
x509.useACMEHost = config.mailserver.fqdn;
|
||||
|
||||
# A list of all login accounts. To create the password hashes, use
|
||||
# nix-shell -p mkpasswd --run 'mkpasswd -s'
|
||||
loginAccounts = {
|
||||
"user1@example.com" = {
|
||||
# Reads the password hash from a file on the server
|
||||
hashedPasswordFile = "/a/file/containing/a/hashed/password";
|
||||
|
||||
# Additional addresses delivered to this mailbox
|
||||
aliases = [ "postmaster@example.com" ];
|
||||
};
|
||||
"user2@example.com" = {
|
||||
# ...
|
||||
# Provides the password hash inline
|
||||
hashedPassword = "$y$j9T$JqqefR6flaaJBRjD4KVZc1$QM6h4Spr5.yn/FuIT.ydTV22daEbiVd8ZprV/POtPgB";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
+230
-131
@@ -5,207 +5,306 @@ Mail servers can be a tricky thing to set up. This guide is supposed to
|
||||
run you through the most important steps to achieve a 10/10 score on
|
||||
`<https://mail-tester.com>`_.
|
||||
|
||||
What you need is:
|
||||
Requirements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- a server running NixOS with a public IP
|
||||
- a domain name.
|
||||
To set up a self-hosted mail server, you need the following:
|
||||
|
||||
* Small (e.g. 1C/2G) server running NixOS
|
||||
* Stable IPv4 and - strongly recommended - IPv6 addresses
|
||||
|
||||
* Ability to configure a Reverse DNS (PTR record) for your IP addresses
|
||||
* Access to SMTP traffic on port 25/tcp - some hoster make you to ask for this
|
||||
|
||||
* A registered domain name with DNS record management access
|
||||
|
||||
Once these requirements are in place, you can begin setting up your selfhosted
|
||||
mailserver.
|
||||
|
||||
.. note::
|
||||
|
||||
In the following, we consider a server with the public IP ``1.2.3.4``
|
||||
and the domain ``example.com``.
|
||||
Below we'll assume that your server got assigned the public IP addresses
|
||||
``192.0.2.1`` (IPv4) and ``2001:db8::1`` (IPv6) and that you control the
|
||||
``example.com`` domain.
|
||||
|
||||
First, we will set the minimum DNS configuration to be able to deploy
|
||||
an up and running mail server. Once the server is deployed, we could
|
||||
then set all DNS entries required to send and receive mails on this
|
||||
server.
|
||||
Configure forward DNS records
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Setup DNS A/AAAA records for server
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Here we set up ``mail.example.com`` as the forward hostname for your mail server
|
||||
to point to the IP addresses allocated to the server. This allows reaching
|
||||
the server under this name and to reference it later in MX records for mail
|
||||
delivery.
|
||||
|
||||
Add DNS records to the domain ``example.com`` with the following
|
||||
entries
|
||||
Now edit the ``example.com`` zone and create the following DNS records:
|
||||
|
||||
==================== ===== ==== =============
|
||||
Name (Subdomain) TTL Type Value
|
||||
==================== ===== ==== =============
|
||||
``mail.example.com`` 10800 A ``1.2.3.4``
|
||||
``mail.example.com`` 10800 AAAA ``2001::1``
|
||||
==================== ===== ==== =============
|
||||
.. csv-table::
|
||||
:header: "Name", "TTL", "Type", "Value"
|
||||
:widths: 30, 10, 10, 50
|
||||
|
||||
If your server does not have an IPv6 address, you must skip the `AAAA` record.
|
||||
mail.example.com., 3600, A, 192.0.2.1
|
||||
mail.example.com., 3600, AAAA, 2001:db8::1
|
||||
|
||||
You can check this with
|
||||
.. note::
|
||||
If your server does not have an IPv6 address, you must skip the ``AAAA``
|
||||
record.
|
||||
|
||||
::
|
||||
Verify DNS record propagation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
$ nix-shell -p bind --command "host -t A mail.example.com"
|
||||
mail.example.com has address 1.2.3.4
|
||||
Before we continue with the next step, we require that the forward DNS record
|
||||
has propagated. For that it's best to check an authoritative nameserver for
|
||||
``example.com`` so that we don't look at cached DNS records.
|
||||
|
||||
$ nix-shell -p bind --command "host -t AAAA mail.example.com"
|
||||
mail.example.com has address 2001::1
|
||||
.. code-block:: console
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated. This
|
||||
DNS entry is required for the Let's Encrypt certificate generation
|
||||
(which is used in the below configuration example).
|
||||
# Find the authoritative nameservers for example.com
|
||||
$ nix-shell -p dig --command "dig NS example.com +short"
|
||||
ns1.example.org.
|
||||
ns2.example.org.
|
||||
|
||||
# Query the A record from an authoritative nameserver
|
||||
$ nix-shell -p dig --command "dig @ns1.example.org A mail.example.com +short"
|
||||
192.0.2.1
|
||||
|
||||
# Query the AAAA record from an authoritative nameserver
|
||||
$ nix-shell -p dig --command "dig @ns1.example.org AAAA mail.example.com +short"
|
||||
2001:db8::1
|
||||
|
||||
|
||||
DNS propagation usually takes a few minutes, so you might need to retry these
|
||||
queries. Once the IP addresses appear you can continue with the next step.
|
||||
|
||||
Setup the server
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The following describes a server setup that is fairly complete. Even
|
||||
though there are more possible options (see the `NixOS Mailserver
|
||||
options documentation <options.html>`_), these should be the most
|
||||
common ones.
|
||||
The following configuration describes a fairly complete mail server, capable
|
||||
of sending and receiving mail for statically configured accounts. It includes
|
||||
encrypted SMTP and IMAP services for secure delivery and retrieval, and relies
|
||||
on ACME HTTP-01 to automatically obtain and maintain a TLS certificate.
|
||||
|
||||
While `more options`_ are available, the configuration below covers the most
|
||||
common settings to get your mail server up and running.
|
||||
|
||||
.. _more options: options.html
|
||||
|
||||
.. literalinclude:: ./setup-example.nix
|
||||
:language: nix
|
||||
|
||||
After a ``nixos-rebuild switch`` your server should be running all
|
||||
mail components.
|
||||
After a ``nixos-rebuild switch`` your server should be running all the necessary
|
||||
mail services.
|
||||
|
||||
Setup all other DNS requirements
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Configure DNS records
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Set rDNS (reverse DNS) entry for server
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Reverse DNS
|
||||
^^^^^^^^^^^
|
||||
|
||||
Wherever you have rented your server, you should be able to set reverse
|
||||
DNS entries for the IP’s you own:
|
||||
Earlier, we configured forward DNS from your hostname to your IP address. Now we
|
||||
will configure reverse DNS so that your IP address points back to your hostname.
|
||||
|
||||
- Add an entry resolving IPv4 address ``1.2.3.4`` to ``mail.example.com``.
|
||||
- Add an entry resolving IPv6 ``2001::1`` to ``mail.example.com``. Again, this
|
||||
must be skipped if your server does not have an IPv6 address.
|
||||
If your forward and reverse DNS do not match, many mail servers will reject or
|
||||
flag your emails as spam, severely impairing delivery.
|
||||
|
||||
Your server provider should allow you to configure reverse DNS (PTR record)
|
||||
records for the IP addresses you control, typically through their control panel
|
||||
or account management interface:
|
||||
|
||||
- Configure ``192.0.2.1`` to point to ``mail.example.com.``
|
||||
- Configure ``2001:db8::1`` to point to ``mail.example.com.``, if you have IPv6
|
||||
addressing
|
||||
|
||||
Alternatively, if you interact with a proper DNS setup, the actual DNS records
|
||||
look like this:
|
||||
|
||||
.. csv-table::
|
||||
:header: "Name", "TTL", "Type", "Value"
|
||||
:widths: 30, 10, 10, 50
|
||||
|
||||
1.2.0.192.in-addr.arpa., 86400, PTR, mail.example.com.
|
||||
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa., 86400, PTR, mail.example.com.
|
||||
|
||||
.. note::
|
||||
Reverse DNS uses reverse notation for naming its records:
|
||||
|
||||
* IPv4 reverses the order of the octets and appends ``in-addr.arpa.``, so
|
||||
``192.0.2.1`` becomes ``1.2.0.192.in-addr.arpa.``
|
||||
* IPv6 fully expands the address and reverses each hex digit before
|
||||
concatenating it with dots and appending ``ip6.arpa.``
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
nix-shell -p haskellPackages.ip6addr --command "ip6addr --ptr 2001:db8::1"
|
||||
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.IP6.ARPA.
|
||||
|
||||
.. warning::
|
||||
|
||||
We don't recommend setting up a mail server if you are not able to
|
||||
set a reverse DNS on your public IP because sent emails would be
|
||||
mostly marked as spam. Note that many residential ISP providers
|
||||
don't allow you to set a reverse DNS entry.
|
||||
We don't recommend setting up a mail server if you are unable to configure
|
||||
reverse DNS on your public IP addresses because mails would inevitable be
|
||||
marked as spam. Note that many residential ISP providers don't allow you to
|
||||
set a reverse DNS entry and prohibit sending mail through policy blocklists
|
||||
like Spamhaus PBL.
|
||||
|
||||
You can check this with
|
||||
DNS propagation often isn't instant, so verify before continuing:
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
$ nix-shell -p bind --command "host 1.2.3.4"
|
||||
4.3.2.1.in-addr.arpa domain name pointer mail.example.com.
|
||||
$ nix-shell -p dig --command "dig -x 192.0.2.1 +short"
|
||||
mail.example.com.
|
||||
|
||||
$ nix-shell -p bind --command "host 2001::1"
|
||||
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.2.ip6.arpa domain name pointer mail.example.com.
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated.
|
||||
|
||||
Set a ``MX`` record
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
$ nix-shell -p dig --command "dig -x 2001:db8::1 +short"
|
||||
mail.example.com.
|
||||
|
||||
|
||||
Add a ``MX`` record to the domain ``example.com``.
|
||||
MX record
|
||||
^^^^^^^^^
|
||||
|
||||
================ ==== ======== =================
|
||||
Name (Subdomain) Type Priority Value
|
||||
================ ==== ======== =================
|
||||
example.com MX 10 mail.example.com
|
||||
================ ==== ======== =================
|
||||
The MX record instructs other mailservers where to deliver mail for a domain
|
||||
name.
|
||||
|
||||
You can check this with
|
||||
Create the MX record for ``example.com`` to point to the hostname of the server.
|
||||
|
||||
::
|
||||
.. csv-table::
|
||||
:header: "Name", "TTL", "Priority", "Type", "Value"
|
||||
:widths: 30, 10, 10, 10, 50
|
||||
|
||||
$ nix-shell -p bind --command "host -t mx example.com"
|
||||
example.com mail is handled by 10 mail.example.com.
|
||||
example.com., 3600, MX, 10, mail.example.com.
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated.
|
||||
The priority field determines the order when multiple servers are configured.
|
||||
It is not important in this scenario but setting a value is mandatory and 10
|
||||
leaves some wiggle room below and above, should you ever need that.
|
||||
|
||||
Set a ``SPF`` record
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
.. code-block:: console
|
||||
|
||||
Add a `SPF <https://en.wikipedia.org/wiki/Sender_Policy_Framework>`_
|
||||
record to the domain ``example.com``.
|
||||
$ nix-shell -p dig --command "dig @ns1.example.org MX example.com +short"
|
||||
10 mail.example.com.
|
||||
|
||||
================ ===== ==== ================
|
||||
Name (Subdomain) TTL Type Value
|
||||
================ ===== ==== ================
|
||||
example.com 10800 TXT `v=spf1 mx -all`
|
||||
================ ===== ==== ================
|
||||
SPF record
|
||||
^^^^^^^^^^
|
||||
|
||||
You can check this with
|
||||
With `SPF`_ we can specify which mail servers are authorized to send mail on
|
||||
behalf of a domain name.
|
||||
|
||||
::
|
||||
.. _SPF: https://en.wikipedia.org/wiki/Sender_Policy_Framework
|
||||
|
||||
$ nix-shell -p bind --command "host -t TXT example.com"
|
||||
example.com descriptive text "v=spf1 mx -all"
|
||||
The SPF record is TXT record and we can tie it in with the MX record we created
|
||||
in the previous step. Finishing with ``-all`` indicates that without any match
|
||||
the mail should be rejected.
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated.
|
||||
.. csv-table::
|
||||
:header: "Name", "TTL", "Type", "Value"
|
||||
:widths: 30, 10, 10, 50
|
||||
|
||||
Set ``DKIM`` signature
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
example.com., 86400, TXT, v=spf1 mx -all
|
||||
|
||||
On your server, the ``rspamd`` systemd service generated a file
|
||||
containing your DKIM public key in the file
|
||||
``/var/dkim/example.com.mail.txt``. The content of this file looks
|
||||
like
|
||||
.. code-block:: console
|
||||
|
||||
::
|
||||
$ nix-shell -p dig --command "dig TXT example.com"
|
||||
v=spf1 mx -all
|
||||
|
||||
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
|
||||
"p=<really-long-key>" ) ; ----- DKIM key mail for nixos.org
|
||||
|
||||
where ``really-long-key`` is your public key.
|
||||
DKIM record
|
||||
^^^^^^^^^^^
|
||||
|
||||
Based on the content of this file, we can add a ``DKIM`` record to the
|
||||
domain ``example.com``.
|
||||
On system activation a `DKIM`_ keypair for ``example.com`` was generated. The
|
||||
mail server uses this key to sign outgoing emails, allowing receiving servers to
|
||||
verify the authenticity of the sender domain and ensuring that the signed parts
|
||||
of the message have not been tampered with.
|
||||
|
||||
=========================== ===== ==== =======================================
|
||||
Name (Subdomain) TTL Type Value
|
||||
=========================== ===== ==== =======================================
|
||||
mail._domainkey.example.com 10800 TXT ``v=DKIM1; k=rsa; p=<really-long-key>``
|
||||
=========================== ===== ==== =======================================
|
||||
.. _DKIM: https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail
|
||||
|
||||
You can check this with
|
||||
Now, check ``/var/dkim/example.com.mail.txt``, which contains the proposed DNS
|
||||
record for the ``mail`` DKIM selector.
|
||||
|
||||
::
|
||||
.. code-block:: none
|
||||
|
||||
$ nix-shell -p bind --command "host -t txt mail._domainkey.example.com"
|
||||
mail._domainkey.example.com descriptive text "v=DKIM1;p=<really-long-key>"
|
||||
mail._domainkey IN TXT ( "v=DKIM1; k=rsa; "
|
||||
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7hSess/UgEjaaq/NDn5KtW2iZzYljhf45DH3tN/kqcJ04JJk/Z1rS7CMJQ/pYZSSnQOju0H25uOtODvhqXPDxDdtCyDSrx54z/38lGNtA76/iWy/ikjb9hEkb2k3HuKex3P4KhhOC1pytDEFnh/T2aBxPNOigc/cpqm1U9RbnAwvArtx9dgOAgiV8rOIgPgyrPw1B3cJG3hgFYU2"
|
||||
"GwXMoiFQPgwm7bkjelmThqXozA7jFJfnYt49jjrIYCv8X/nQx9cNpVAv2852mhU/3uuy6sa4MPjT6RiK9BJCMyDnqSpTPCjIubL4VhGCuzp7RPBkayWnlaH0X8PWGq6BQ0eBwIDAQAB"
|
||||
) ;
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated.
|
||||
Based on the content of this file, we can create the DKIM TXT record for the
|
||||
``mail`` selector in the ``example.com`` zone. For the ``p=`` value, glue the
|
||||
two long strings back together without any quotes and spaces and put them into
|
||||
your record below.
|
||||
|
||||
Set a ``DMARC`` record
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. csv-table::
|
||||
:header: "Name", "TTL", "Type", "Value"
|
||||
:widths: 30, 10, 10, 50
|
||||
|
||||
Add a ``DMARC`` record to the domain ``example.com``.
|
||||
example.com., 86400, TXT, v=DKIM1; k=rsa; p=MIIBIjANBgk...Q0eBwIDAQAB
|
||||
|
||||
======================== ===== ==== ====================
|
||||
Name (Subdomain) TTL Type Value
|
||||
======================== ===== ==== ====================
|
||||
_dmarc.example.com 10800 TXT ``v=DMARC1; p=none``
|
||||
======================== ===== ==== ====================
|
||||
.. code-block:: console
|
||||
|
||||
You can check this with
|
||||
$ nix-shell -p dig --command "dig @ns1.example.org TXT mail._domainkey.example.com +short"
|
||||
"v=DKIM1; k=rsa; p=MIIBIjANBgk...Q0eBwIDAQAB"
|
||||
|
||||
::
|
||||
|
||||
$ nix-shell -p bind --command "host -t TXT _dmarc.example.com"
|
||||
_dmarc.example.com descriptive text "v=DMARC1; p=none"
|
||||
DMARC record
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Note that it can take a while until a DNS entry is propagated.
|
||||
Finally, DMARC lets you define a policy for how strictly SPF and DKIM should be
|
||||
checked and how to handle validation failures. For a new server, it’s important
|
||||
to have a DMARC record in place, even if it doesn’t enforce any actions yet,
|
||||
because it improves deliverability by showing receiving servers that your domain
|
||||
is properly managed and reducing the risk of email spoofing.
|
||||
|
||||
.. csv-table::
|
||||
:header: "Name", "TTL", "Type", "Value"
|
||||
:widths: 30, 10, 10, 50
|
||||
|
||||
_dmarc.example.com., 86400, TXT, v=DMARC1; p=none;
|
||||
|
||||
Verify propagation one final time.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ nix-shell -p dig --command "dig @ns1.example.org TXT _dmarc.example.com"
|
||||
"v=DMARC1; p=none"
|
||||
|
||||
|
||||
Test your Setup
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Write an email to your aunt (who has been waiting for your reply far too
|
||||
long), and sign up for some of the finest newsletters the Internet has.
|
||||
Maybe you want to sign up for the `SNM Announcement
|
||||
List <https://www.freelists.org/list/snm>`__?
|
||||
Write an email to your aunt — she’s been waiting far too long for your reply,
|
||||
and this is your chance to finally make her day. Or, if you prefer a less
|
||||
emotional test, send a message to `mail-tester.com`_ to see how your outgoing
|
||||
mail scores.
|
||||
|
||||
Besides that, you can send an email to
|
||||
`mail-tester.com <https://www.mail-tester.com/>`__ and see how you
|
||||
score, and let `mxtoolbox.com <http://mxtoolbox.com/>`__ take a look at
|
||||
your setup, but if you followed the steps closely then everything should
|
||||
be awesome!
|
||||
You can also let `MXToolbox`_ take a peek at your setup. If you followed the
|
||||
steps carefully, everything should be working perfectly!
|
||||
|
||||
Next steps (optional)
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
.. _mail-tester.com: https://mail-tester.com/
|
||||
.. _MXToolbox: https://mxtoolbox.com/
|
||||
|
||||
Take a look through our `Advanced Configurations <advanced-configurations.html>`_.
|
||||
|
||||
Join the community
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The community has a lively chat room on Matrix at `#nixos-mailserver:nixos.org`_
|
||||
where you can ask questions, get help, share ideas, or discuss contributions.
|
||||
|
||||
.. _#nixos-mailserver:nixos.org: https://matrix.to/#/#nixos-mailserver:nixos.org
|
||||
|
||||
Next steps
|
||||
~~~~~~~~~~
|
||||
|
||||
Your server scored perfect results already, so these steps are entirely
|
||||
optional.
|
||||
|
||||
Are you feeling adventurous? Dive into our `advanced configurations`_ to explore
|
||||
additional features and capabilities that let you fine-tune and extend your
|
||||
mail setup.
|
||||
|
||||
If you want to take things even further, more elaborate testing services can
|
||||
give you a clearer picture of your mail service and suggest ways to improve
|
||||
it.
|
||||
|
||||
- `internet.nl`_ (supported by the Dutch Governement)
|
||||
- `MECSA`_ (supported by the European Commission)
|
||||
|
||||
Finally, you can also browse the full list of `options`_ provided by NixOS mailserver.
|
||||
|
||||
.. _advanced configurations: advanced-configurations.html
|
||||
.. _options: options.html
|
||||
.. _internet.nl: https://internet.nl/test-mail/
|
||||
.. _MECSA: https://mecsa.jrc.ec.europa.eu/
|
||||
|
||||
Reference in New Issue
Block a user