******************** Customizing Raspbian ******************** .. include:: rpi_disclaimer.rst The Raspbian operating system is the official OS for the Raspberry Pi, and arguably, the best supported. More important for my purposes is the fact that it is based on Debian Linux, my OS of choice for over 20 years now. These pages summarize the steps that I take to customize a freshly-installed raspbian image to my liking, over-riding many of the annoying and insecure defaults. These steps are all performed using the command line, avoiding menu-driven configuration programs or editors to allow scripting. You may, of course, use an editor to make the changes shown below as you see fit. This isn't really meant to be a hand-hold tutorial, so you'll want to change the steps shown here to suit your preferred configuration method. In particular, I use command-line edits using the ``sed`` editor that you might wish to make using your preferred text editor. I use these steps to create a master image, which I copy to disk, then burn a copy to microSD whenever doing a new install on a Raspberry Pi. Eventually, I plan to convert all of these steps into Ansible playbooks to completely automate my configuration process, including keeping running devices up to my baseline configuration. Most of these steps apply to any other debian-based distribution, so can be used on non-Raspberry Pi computers. Update installed packages ========================= Update the installation cache from the raspbian repository:: sudo apt update Update installed packages to the latest version:: sudo apt -y dist-upgrade Install preferred packages ========================== I like to install a variety of packages to customize or enhance the default configuration:: sudo apt -y install \ fail2ban \ openssh-server \ openssh-client \ tmux \ byobu \ molly-guard \ unattended-upgrades \ python-pip \ virtualenv \ virtualenv-clone \ virtualenvwrapper \ libraspberrypi-dev \ git \ zsh \ vim \ slay \ lsof \ traceroute \ iperf \ iftop \ nmap \ lynx \ curl \ htop \ locales \ localepurge \ deborphan \ exfat-fuse \ exfat-utils \ fbi \ dcfldd \ durep \ ufw \ time \ transmission-cli \ uprecords-cgi \ uptimed \ ssmtp \ mailutils \ rpi-update Some of these are already installed, but I specify them here to keep track across raspbian versions. Non-raspbian debian-based distributions may not include some by default, so I specify them here. The ``apt`` installation tools are smart enough to identify those already installed and simply skip them. Here's a breakdown of these packages: Security & system hardening --------------------------- * fail2ban: block access on repeated access attempts. * openssh-server: ssh server programs * openssh-client: ssh client and support programs * unattended-upgrades automated installation of security updates * molly-guard: require entering hostname to reboot via ssh * nmap: network port scanning and testing * ufw: simple firewall based on iptables Development tools ----------------- * git: source code version control * libraspberrypi-dev: raspberry pi development libraries * python-pip: pip installer for python libraries * python-dev: python development libraries * virtualenv: python virtual enviornment manager * virtualenv-clone: clone virtual python installation * virtualenvwrapper: System configuration & maintenance ---------------------------------- * slay: kill all programs associated with a user * htop: console-based system monitor * locales: manage locales * localepurge: remove cache files for unused locales * deborphan: remove unused installation packages * exfat-fuse: filesystem support for exfat * exfat-utils: support programs for exfat filesystem * lsof: view open files and network connections * iperf: network performance monitor * rpi-update: update rpi firmware to bleeding edge * traceroute: trace netwnork path to destination * dcfldd: enhanced disk imager support multiple concurrent writes * uprecords-cgi: view system uptime milestones * uptimed: track system uptime * iftop: monitor network interface * time: time program execution and resources * ssmtp: simple, secure ssmtp mail server Preferred applications & tools ------------------------------ * vim: enhanced vi-like editor * zsh: enhanced shell * byobu: terminal multiplexer * tmux: terminal multiplexer * fbi: display images on framebuffer (for splash screens) * durep: console-based disk utilization mapper * lynx: command-line web browser * curl: work with web pages from the command-line * transmission-cli: command-line bittorrent client * mailutils: send and read email at the command-line Localization ============ Raspbian ships configured for a ``GB`` user, including locale, timezone and keyboard settings. These are the steps I use to set it up for my ``US``-based setup. Configure timezone ------------------ Set the timezone to ``US/Eastern``:: sudo rm /etc/localtime sudo ln -s /usr/share/zoneinfo/US/Eastern /etc/localtime echo "US/Eastern" | sudo tee -a /etc/timezone sudo dpkg-reconfigure -f noninteractive tzdata Configure locales ----------------- Remove unneeded default ``GB`` locales and generate ``US.UTF-8`` locales:: sudo apt -y install localepurge sudo sed -ri -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen sudo sed -ri -e 's/en_GB.UTF-8 UTF-8/# en_GB.UTF-8 UTF-8/' /etc/locale.gen echo 'LANG="en_US.UTF-8"' | sudo tee -a /etc/default/locale sudo dpkg-reconfigure --frontend=noninteractive locales sudo LANG=en_US.UTF-8 && update-locale Set keyboard type to US ----------------------- Install console configuration utility:: sudo apt -y install console-data Edit or replace ``/etc/default/keyboard`` with:: # KEYBOARD CONFIGURATION FILE # Consult the keyboard(5) manual page. XKBMODEL="pc105" XKBLAYOUT="us" XKBVARIANT="" XKBOPTIONS="" BACKSPACE=“guess" Update console data:: sudo dpkg-reconfigure --frontend=noninteractive console-data Improve console readability and appearance ========================================== Set console font to something readable at 1080p. Install ``inconsolata`` console font:: apt install -y fonts-inconsolata Edit ``/etc/default/console-setup``:: # CONFIGURATION FILE FOR SETUPCON # Consult the console-setup(5) manual page. ACTIVE_CONSOLES="/dev/tty[1-6]" CHARMAP="UTF-8" CODESET="guess" FONTFACE="Terminus" FONTSIZE="16x32" VIDEOMODE= # The following is an example how to use a braille font # FONT='lat9w-08.psf.gz brl-8x8.psf' Change system-wide default editor ================================= One of the best decisions I made early-on in my Linux learning was to learn the ``vim`` editor. While there's nothing wrong with the default ``nano`` editor, I find it a bit ironic that an editor that emulates WordStar of old is considered more user friendly. Feel free to skip this step if you're more comfortable with a different editor. Set default system-wide editor to ``vim``:: apt install -y vim sudo update-alternatives --set editor /usr/bin/vim.basic Change hostname =============== Let's face it: typing "raspberrypi" repeatedly gets tedious fast. And once you've got more than one Raspberry Pi running, you need to differentiate between them. Renaming your Pi by changing the hostname is the easiest way to fix this:: # change localhost reference in /etc/hosts sudo sed -i "s/127.0.1.1.*raspberrypi\t/g" /etc/hosts # change system hostname file sudo sed -i "s/raspberrypi//g" /etc/hostname # change system mailname file (if present) sudo sed -i "s/raspberrypi//g" /etc/mailname Replace all occurrences of ```` with your chosen hostname *without* the angle brackets. Test changes ============ At this point, you've done a lot of system tweaking. Although not absolutely necessary, rebooting at this point and testing your changes is a good idea. Notably, the hostname should be changed before proceeding with some of the following steps. Be sure to connect using the new hostname before proceeding. Configuring wifi ================ There are multiple ways to configure wifi on raspbian. The most flexible for my usual headless configuration is through editing the ``/etc/wpa/wpa_supplicant.conf`` file. The advantages of this approach include: * Support for configuring country-specific wifi parameters. * Support for seamlessly connecting to multiple networks (SSIDs) without reconfiguration. * Support for prioritization of SSID connections when multiple are available. * Support for encrypted pre-shared keys (passwords) in the configuration file. Country-specific configuration ------------------------------ Wifi networks operate on unlicensed frequency bands, meaning anybody can use them. However, this does not mean there aren't restrictions. The specific frequencies available vary from jurisdiction to jurisdiction, as do rules for maximum output power. To avoid possible legal consequences and be a good neighbor in general, set the ``country=`` parameter:: country=US SSID configuration ------------------ You can configure your ``wpa_supplicant.conf`` file to support roaming between multiple networks (each identified by a unique SSID) and attach automatically whenever one is in range. This is done by adding a ``network=`` stanza to the configuration. At minimum, each stanza must contain the following lines: * ``ssid=`` identifies the "service set identifier" (SSID) or name of your wifi network. The ssid should be specified in quotes. * ``psk=`` identifies the "pre-shared key" (PSK) or password associated with the SSID. The psk should be specified in quotes. Here's a simple example:: network={ ssid="MySSID" psk="mypassphrase" } Pre-shared key encryption ------------------------- Note that the psk is stored in unencrypted, clear-text in the configuration file. Although access to the file is restricted, there is always a chance someone might stumble across this information. It is good practice to encrypt passwords stored on disk. The ``wpa_passphrase`` command can be used to generate an encrypted psk given your SSID and PSK:: $ wpa_passphrase MySSID mypassphrase network={ ssid="MySSID" #psk="mypassphrase" psk=9c399aba03129af0a86838780444a85fe5dff2cf341da3e0f78e32d1e3f0a45a } Note that the encrypted psk is listed *without* quotes, whereas the clear-text version is enclosed in quotes. You could simply paste these lines verbatim into your ``wpa_supplicant.conf`` file. However, after testing, removal of the clear-text ``#psk=`` line is recommended. Open network configuration -------------------------- If you are connecting to an open wifi network such as a hotel, you'll need to add an open network clause:: network={ ssid="Hotel_Wi-Fi" key_mgmt=NONE } .. caution:: Please be sure to follow the recommended security hardening steps in this document when connecting to any network you don't explicitly control! Identifying the network ----------------------- Assigning an ``id_str=`` line is optional, but can be useful to differentiate between wireless networks within ``/etc/network/interfaces``. If no ``id_str`` is specified, it defaults to ``default``. Assigning network priority -------------------------- Each network can be assigned a ``priority=`` parameter. If multiple networks are available, those with the highest priority will be selected. If two networks have the same priority, the one with the strongest signal will be selected. Unless specified, priority is set to 0. I use this feature when doing testing. I may have a testing wifi network, or a cellular hotspot running that I want to connect to if available, but otherwise default to whatever's available locally. Putting it all together ----------------------- Here's an example of a complete ``/etc/wpa_supplicant/wpa_supplicant.conf`` supporting multiple networks, each with unique SSIDs and priorities:: country=US ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="Home" #psk="HomePassphrase" <- REMOVE AFTER TESTING psk=b1eb83db900dbc2732533068dfff2bf04c280044cd195cab49a0f4a7a9f58f12 id_str="Home" priority=1 } network={ ssid="Hotspot" #psk="HostspotPassprhase" <- REMOVE AFTER TESTING psk=5830fa80d18950468460b415b3e2ad40c41ad804710e15e9a438f95970d339ca id_str="Field" priority=10 } network={ ssid="Hotel_Wi-Fi" key_mgmt=NONE } .. todo:: Incorporate: * ``proto=WPA2`` * ``key_mgmt=WPA-PSK`` * ``pairwise=CCMP`` * ``group=CCMP`` Configure ssmtp for sending email ================================= ``ssmtp`` is described in the debian repositories as "A secure, effective and simple way of getting mail off a system to your mail hub". It has just enough smarts to pass local mail off to your main email relay, and nothing more. It doesn't handle incoming mail at all, so security concerns are minimized. I like to use it to send admin notification emails and the like. Configure ssmtp:: sed -i "s/root=.*/root=/g" /etc/ssmtp/ssmtp.conf sed -i "s/hostname=.*/hostname=/g" /etc/ssmtp/ssmtp.conf sed -i "s/mailhub=.*/mailhub=/g" /etc/ssmtp/ssmtp.conf sed -i "s/rewriteDomain=.*$/rewriteDomain=/g" /etc/ssmtp/ssmtp.conf sed -i "s/usetls=.*$//g" /etc/ssmtp/ssmtp.conf sed -i "$ i usetls=yes" /etc/ssmtp/ssmtp.conf sed -i "s/usestarttls=.*$//g" /etc/ssmtp/ssmtp.conf sed -i "$ i usestarttls=yes" /etc/ssmtp/ssmtp.conf sed -i "s/authuser=.*$//g" /etc/ssmtp/ssmtp.conf sed -i "$ i authuser=" /etc/ssmtp/ssmtp.conf sed -i "s/authpass=.*$//g" /etc/ssmtp/ssmtp.conf sed -i "$ i authpass=" /etc/ssmtp/ssmtp.conf Configure uptimed for tracking system uptime ============================================ ``uptimed`` tracks your system uptime, and optionally sends you notification emails when milestones or records are hit. This can be useful for tracking your system availability and generally bragging about system stability. Here's an example of the output it generates:: % uprecords # Uptime | System Boot up ----------------------------+--------------------------------------------------- -> 1 43 days, 11:03:00 | Linux 4.9.35-v7+ Wed Sep 20 02:38:48 2017 2 18 days, 05:41:20 | Linux 4.9.35-v7+ Thu Aug 31 12:35:57 2017 3 1 day , 06:44:25 | Linux 4.9.35-v7+ Mon Sep 18 18:17:14 2017 ----------------------------+--------------------------------------------------- NewRec 25 days, 05:21:39 | since Sun Oct 8 08:20:08 2017 up 62 days, 23:28:45 | since Thu Aug 31 12:35:57 2017 down 0 days, 01:37:06 | since Thu Aug 31 12:35:57 2017 %up 99.893 | since Thu Aug 31 12:35:57 2017 Configure uptimed:: sed -i "s/EMAIL=.*/EMAIL=/g" /etc/uptimed.conf sed -i "s/SEND_EMAIL=.*/SEND_EMAIL=1/g" /etc/uptimed.conf Install versacrypt ================== ``Versacrypt`` provides robust, cross-platform file encryption. Install versacrypt:: wget https://launchpad.net/veracrypt/trunk/1.19/+download/veracrypt-1.19-raspbian-setup.tar.bz2 bunzip2 veracrypt-1.19-raspbian-setup.tar.bz2 tar -xpvf veracrypt-1.19-raspbian-setup.tar chmod +x ./veracrypt-1.19-setup-console-armv7 sudo ./veracrypt-1.19-setup-console-armv7 Install syncthing ================= ``syncthing`` provides cross-platform, peer-to-peer file synchornization much like ``dropbox``, but without the need to store data on 3rd party servers. It's great for file synchronization that "just works" once configured. I use it for: * Editing the source files for these pages on my non-Linux laptop using the ``Sublime Text`` editor for ease of formatting. Often times, I'm editing files when completely disconnected from the Internet. * When I'm back in network range, ``syncthing`` syncs the source files over to my raspberry pi where I generate the html pages. I currently do this manually, but plan to automate the detection of changes and triggering the build. * When connected to the Internet, ``syncthing`` synchronizes the generated static html pages to my cloud-hosted server where they are served using ``nginx`` for speedy rendering. (This is what you are viewing now.) Install syncthing peer-to-peer file synchronization:: wget -O - https://syncthing.net/release-key.txt | sudo apt-key add - echo "deb http://apt.syncthing.net/ syncthing release" | sudo tee -a /etc/apt/sources.list.d/syncthing-release.list sudo apt update sudo apt -y install syncthing While it is possible to configure the ``syncthing`` configuration web page service to listen on a network-facing port, this is generally not a good idea, especially if your Raspberrry Pi is going to be moved around on different networks. Instead, access the webpage listening to a local-only (localhost) port on the Raspberry Pi using the port tunneling feature of ``ssh``. On your computer, access the Raspberry Pi using:: ssh -L 8000:localhost:8384 hostname This will connect to your Raspberry Pi via ``ssh`` and create a tunnel mapping port 8000 *on your computer* to port 8384 (the ``syncthing`` configuration page) listening to port 8384 *on the Raspberry Pi*. Acces the configuration webpage by opening a browser on your computer and opening ``http:://localhost:8000``. You will need to login to the Raspberry Pi using ``ssh`` in this manner to administer ``syncthing``. Hardening the system ==================== The Raspberry Pi foundation made some unfortunate decisions regarding security that pose unacceptable risks for any system that might be exposed to the outside world. Most notably, they configured the system to automatically login as the default ``pi`` user with the password ``raspberry`` on every new install. To make things worse, they gave the ``pi`` user root-level access via the ``sudo`` command without even entering a password. As a result, any Rasperry Pi exposed to the Internet is quickly identified and compromised with the default settings. While they made enabling ``ssh`` a separate step and inserted cautions, these measures are woefully inadequate. Harden ssh server configuration ------------------------------- The first set of steps involve hardening the ``ssh`` server configuration on our Raspberry Pi. Regenerate ssh host keys ^^^^^^^^^^^^^^^^^^^^^^^^ Host keys uniquely identify the computer (host) you are connecting to. This provides mutual protection to both you and the host you're logging into as ``ssh`` uses keys to verify both the user and the target host. If one or the other is changed, ``ssh`` will detect this and reject the connection (if using user keys), or issue warnings (if using host keys). Regenerate ``ssh`` host keys for our newly-updated Raspberry Pi:: sudo rm -v /etc/ssh/ssh_host_* sudo dpkg-reconfigure openssh-server .. note:: This should be done after renaming *and rebooting* the host If you have previously connected to your Raspberry Pi via ``ssh``, the host keys have changed. On your next connection attempt, you will probably see a scary message like this:: % ssh yourname@raspberrypi @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: POSSIBLE DNS SPOOFING DETECTED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ The ECDSA host key for dietpi has changed, and the key for the corresponding IP address X.X.X.X has a different value. This could either mean that DNS SPOOFING is happening or the IP address for the host and its host key have changed at the same time. Offending key for IP in /Users/yourname/.ssh/known_hosts:24 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that a host key has just been changed. The fingerprint for the ECDSA key sent by the remote host is SHA256:ugjH7k9iCEgjxO7r3BcNAkWKI/UieejLJ25QyJ2C/xQ. Please contact your system administrator. Add correct host key in /Users/yourname/.ssh/known_hosts to get rid of this message. Offending ECDSA key in /Users/yourname/.ssh/known_hosts:50 ECDSA host key for dietpi has changed and you have requested strict checking. Host key verification failed. This is ``ssh`` letting you know that the host keys changed, which is a *good* thing. To get rid of this message, do the following:: ssh-keygen -R X.X.X.X If you receive similar warnings about the hostname, try:: ssh-keygen -R Create a non-default user account ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ There are reportedly some programs that depend on the ``pi`` user to run, although I've yet to encounter any after several years of using the Raspberry Pi. Just to be cautious, I create a non-default user account with the same access rights as the ``pi`` user, then simply disable the ``pi`` account in case I do find I need it later. Create a non-default user account for system access:: sudo adduser --gecos "Your Name,,," for NAME in $(groups pi| cut -f 1-3 -d " " --complement); do sudo adduser $NAME; done sudo usermod -a -G sudo Replace all instances of ```` with your chosen single-word username without angle brackets. Always select a strong password. Create system ``ssh`` user group ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ By default, openssh is configured to allow any user with a valid username and password access. If you connect any system to the Internet, you'll quickly find your system bombarded by automated login attempts using a bewildering array of usernames and passwords culled from lists of defaults and common passwords. Rather than take the chance that an installed program or careless user uses a weak password, I prefer to restrict ``ssh`` access to only those users I explicitly permit access. This is done by creating a system ``sshusers`` group:: sudo addgroup --system sshusers Only users added explicitly to the ``sshusers`` group will be permitted access. Add the newly-created non-default user to ssh user group:: sudo adduser sshusers Harden the ssh server ^^^^^^^^^^^^^^^^^^^^^ Finally, configure ``ssh`` to enforce these restrictions: * Permit only members of the ``sshusers`` group access via ``ssh``. * Allow root access only using key-based access. (Note: disable all root access by setting to 'no') * Permit access from our local network using passwords. * Require keys if accessing from anywhere else. Edit ``/etc/ssh/sshd_config`` to include:: # restrict ssh access to specific users AllowGroups sshusers # allow root access only with ssh keys # unless needed, disable completely with 'no' PermitRootLogin without-password # permit password from rfc1918 local addresses # edit to match your local network Match Address 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16 PasswordAuthentication yes # global option no password auth (keys only) PasswordAuthentication no Change the IP range specified in the ``Match Address`` line to match your network(s). Remember that you will only be able to connect using password authentication when both you and the Raspberry Pi are on specified network address ranges. .. todo:: Add detail on changing to non-default port Restart and test hardened ssh configuration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. Caution:: It is easy to lock yourself out of your system if you are using ``ssh`` for access. If you make a mistake during configuration, you might be prevented from logging in again. Keep your initial ``ssh`` login open in a separate window or session while testing your new account. If you make a mistake, you are still logged in as the default ``pi`` user and can fix things. Restart the ``ssh`` service:: sudo systemctl restart ssh Test your new account by logging in via `ssh` and confirming that you can gain root access using ``sudo``. If this doesn't work, you can make fixes using your ``pi`` user connection (if you didn't close it). Only close your ``pi`` user session after testing this step. Defang the pi user account ^^^^^^^^^^^^^^^^^^^^^^^^^^ Once you are certain your new account is fully functional and that you won't lock yourself out, defang the ``pi`` user account. If we ever need the account, we can re-enable it. Change the ``pi`` user password:: passwd pi Lock and expire the ``pi`` user account:: passwd —lock pi usermod —expiredate 1 pi Remove the ``pi`` user from the ``sudo`` group:: sudo deluser pi sudo Comment out the ``pi`` user from the ``sudoers`` configuration file:: sudo sed -ri -e 's/pi ALL=(ALL) NOPASSWD: ALL/# pi ALL=(ALL) NOPASSWD: ALL/' /etc/sudoers.d/010_pi-nopasswd Add public keys to ssh authorized_keys ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. Caution:: If you move the Raspberry Pi to a network not listed in the ``Match Address`` stanza in ``/etc/ssh/sshd_config``, you will only be able to log in with ``ssh`` using keys listed in your user's ``~/.ssh/authorized_keys`` file *on the target (Raspberry Pi) system*. Be sure to copy over your public key (typically ``~/.ssh/id_rsa.pub``) to the Raspberry Pi before attempting to connect using it! Connect to the Raspberry Pi using your user account and set up public key authentication for your user. You should be logged in using the account you will be using for remote access at this point. Verify that your ``~/.ssh`` folder exists:: ls -ld ~/.ssh drwx------ 3 yourname yourname 4096 Oct 18 13:03 /home/yourname/.ssh Note the ``drwx------`` permissions. This indicates that ``.ssh`` is a directory (d) with read, write and execute permissions for the user (yourname) and no permissions for others. See ``man chmod`` for more details on file permissions. These permissions must be set correctly for ``ssh`` access. .. Caution:: Incorrect setting of `~/.ssh`` directory permissions can prevent access using public keys. If ``~/.ssh`` doesn't exist, create it and limit access to your user only:: mkdir ~/.ssh # create the directory chmod go-rwx ~/.ssh # remove read, write and execute for group and others Next, we need to create the ``~/.ssh/authorized_keys`` file if it doesn't exist. ``ssh`` stores public keys for authorized access in this file. *Without your public key in this file, you will not be able to use key-based authentication to access the Raspberry Pi*. If password authentication is not enabled for the network you are connecting from, you can be locked out. Verify ``~/.ssh/authorized_keys`` does not exist:: ls -l ~/.ssh/authorized_keys ls: cannot access '/home/yourname/.ssh/authorized_keys': No such file or directory If the file does not exist, create it and set secure access permissions:: touch ~/.ssh/authorized_keys ls -l ~/.ssh/authorized_keys -rw-r--r-- 1 yourname yourname 0 Oct 20 15:41 /home/yourname/.ssh/authorized_keys chmod go-rwx authorized_keys ls -l ~/.ssh/authorized_keys -rw------- 1 yourname yourname 0 Oct 20 15:41 /home/yourname/.ssh/authorized_keys .. Caution:: Incorrect setting of ``~/.ssh/authorized_keys`` file permissions can prevent access using public keys. .. todo:: Add detail on copying public keys. Append the contents of your public key (usually ``~/.ssh/id_rsa.pub``) *on the computer that you will be using to connect to the Raspberry Pi from* to the ``~/.ssh/authorized_keys`` file *on the Raspberry Pi* you will be connecting to. Append (do not overwrite) the contents of your public key file (with the ``.pub`` extension) to ``~/.ssh/authorized_keys``:: cat >> ~/.ssh/authorized_keys .. caution:: Be sure to copy over the *public* key file, not your *private* key. By default, public keys have the ``.pub`` file extension. If connecting using the openssh client (recommended), you can specify the ``-v`` option multiple times to get additional troubleshooting detail. There is a *lot* of information, but you'll usually find the cause of any problems in the output if you read carefully:: ssh -vvv @ Bonus Tip: Don't use login names for email ------------------------------------------ You should avoid giving a potential attacker more information than necessary to access your system. A popular method of finding user login names is to scrape the web for email accounts. I've seen email account names that I created over a decade ago and long-since abandoned used in automated login attempts, which implies *someone is taking the trouble to associate a stock of email accounts with my domain and automating the access attempts against my system*. Fortunately, my login usernames and email account names are entirely different. By restricting ``ssh`` access to only users explicitly listed in my ``sshusers`` group as described above, I've eliminated these accounts as a threat. If you are setting up your own email server, in addition to a host of other methods to secure the system that you can find elsewhere, set up email-only accounts that are not used for anything but email access, and be sure *not* to include these in your ``sshusers`` group. .. include:: rpi_footer.rst