{"id":3517,"date":"2025-12-27T19:04:26","date_gmt":"2025-12-27T16:04:26","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/ssh-key-management-and-access-sharing-secure-vps-login-architecture-for-small-teams\/"},"modified":"2025-12-27T19:04:26","modified_gmt":"2025-12-27T16:04:26","slug":"ssh-key-management-and-access-sharing-secure-vps-login-architecture-for-small-teams","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/ssh-key-management-and-access-sharing-secure-vps-login-architecture-for-small-teams\/","title":{"rendered":"SSH Key Management and Access Sharing: Secure VPS Login Architecture for Small Teams"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>When a small team starts managing one or more <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a> servers, SSH access is usually the first thing that gets messy. Developers share a single root password \u201cjust for now\u201d, contractors get shell access without an expiry date, old colleagues keep their keys on the server for years, and nobody is 100% sure who can log in where. You don\u2019t need a big enterprise or an expensive identity provider to fix this; you need a clear SSH key management and access sharing model that fits a small team\u2019s reality.<\/p>\n<p>In this article, we\u2019ll design a practical, secure SSH login architecture for small teams using a VPS at dchost.com or your own dedicated\/colocation server. We\u2019ll walk through how to structure Linux users and groups, how to manage SSH keys without spreadsheets and panic, how to share access safely with team members and contractors, and how to rotate keys when someone leaves. The goal is simple: predictable, auditable SSH access, without turning daily work into bureaucracy.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#Why_SSH_Key_Management_Matters_So_Much_for_Small_Teams\"><span class=\"toc_number toc_depth_1\">1<\/span> Why SSH Key Management Matters So Much for Small Teams<\/a><\/li><li><a href=\"#Core_Building_Blocks_Users_Groups_and_SSH_Keys\"><span class=\"toc_number toc_depth_1\">2<\/span> Core Building Blocks: Users, Groups and SSH Keys<\/a><ul><li><a href=\"#1_One_Linux_user_per_human_no_shared_accounts\"><span class=\"toc_number toc_depth_2\">2.1<\/span> 1. One Linux user per human \u2013 no shared accounts<\/a><\/li><li><a href=\"#2_Groups_define_what_a_person_is_allowed_to_do\"><span class=\"toc_number toc_depth_2\">2.2<\/span> 2. Groups define what a person is allowed to do<\/a><\/li><li><a href=\"#3_SSH_keys_instead_of_passwords\"><span class=\"toc_number toc_depth_2\">2.3<\/span> 3. SSH keys instead of passwords<\/a><\/li><\/ul><\/li><li><a href=\"#Designing_a_Secure_SSH_Access_Architecture_for_a_Small_Team\"><span class=\"toc_number toc_depth_1\">3<\/span> Designing a Secure SSH Access Architecture for a Small Team<\/a><ul><li><a href=\"#1_Basic_architecture_for_one_VPS_and_a_small_team\"><span class=\"toc_number toc_depth_2\">3.1<\/span> 1. Basic architecture for one VPS and a small team<\/a><\/li><li><a href=\"#2_Bastion_jump_host_for_multiple_servers\"><span class=\"toc_number toc_depth_2\">3.2<\/span> 2. Bastion (jump) host for multiple servers<\/a><\/li><li><a href=\"#3_Root_access_model_do_you_ever_SSH_as_root\"><span class=\"toc_number toc_depth_2\">3.3<\/span> 3. Root access model: do you ever SSH as root?<\/a><\/li><\/ul><\/li><li><a href=\"#Practical_SSH_Key_Management_Workflows\"><span class=\"toc_number toc_depth_1\">4<\/span> Practical SSH Key Management Workflows<\/a><ul><li><a href=\"#1_Standardize_how_keys_are_created\"><span class=\"toc_number toc_depth_2\">4.1<\/span> 1. Standardize how keys are created<\/a><\/li><li><a href=\"#2_Distribute_keys_to_servers_in_a_controlled_way\"><span class=\"toc_number toc_depth_2\">4.2<\/span> 2. Distribute keys to servers in a controlled way<\/a><\/li><li><a href=\"#3_Keep_a_living_inventory_of_who_has_which_keys\"><span class=\"toc_number toc_depth_2\">4.3<\/span> 3. Keep a living inventory of who has which keys<\/a><\/li><li><a href=\"#4_Key_rotation_and_offboarding_workflow\"><span class=\"toc_number toc_depth_2\">4.4<\/span> 4. Key rotation and offboarding workflow<\/a><\/li><\/ul><\/li><li><a href=\"#Access_Sharing_Without_Chaos_Contractors_Deployments_and_Service_Accounts\"><span class=\"toc_number toc_depth_1\">5<\/span> Access Sharing Without Chaos: Contractors, Deployments and Service Accounts<\/a><ul><li><a href=\"#1_Give_contractors_their_own_users_with_an_expiry_plan\"><span class=\"toc_number toc_depth_2\">5.1<\/span> 1. Give contractors their own users \u2013 with an expiry plan<\/a><\/li><li><a href=\"#2_Deployment_keys_and_restricted_commands\"><span class=\"toc_number toc_depth_2\">5.2<\/span> 2. Deployment keys and restricted commands<\/a><\/li><li><a href=\"#3_Read-only_access_for_audits_and_troubleshooting\"><span class=\"toc_number toc_depth_2\">5.3<\/span> 3. Read-only access for audits and troubleshooting<\/a><\/li><\/ul><\/li><li><a href=\"#Advanced_Options_FIDO2_Keys_SSH_Certificates_and_Bastions\"><span class=\"toc_number toc_depth_1\">6<\/span> Advanced Options: FIDO2 Keys, SSH Certificates and Bastions<\/a><ul><li><a href=\"#1_FIDO2_hardware_keys_for_high-value_servers\"><span class=\"toc_number toc_depth_2\">6.1<\/span> 1. FIDO2 hardware keys for high-value servers<\/a><\/li><li><a href=\"#2_SSH_certificate_authority_SSH_CA_for_centralized_trust\"><span class=\"toc_number toc_depth_2\">6.2<\/span> 2. SSH certificate authority (SSH CA) for centralized trust<\/a><\/li><li><a href=\"#3_Remote_access_from_multiple_locations_and_networks\"><span class=\"toc_number toc_depth_2\">6.3<\/span> 3. Remote access from multiple locations and networks<\/a><\/li><\/ul><\/li><li><a href=\"#Logging_Auditing_and_Compliance-Friendly_SSH_Usage\"><span class=\"toc_number toc_depth_1\">7<\/span> Logging, Auditing and Compliance-Friendly SSH Usage<\/a><ul><li><a href=\"#1_System_logs_who_logged_in_and_from_where\"><span class=\"toc_number toc_depth_2\">7.1<\/span> 1. System logs: who logged in and from where<\/a><\/li><li><a href=\"#2_Command_auditing_with_sudo_and_shells\"><span class=\"toc_number toc_depth_2\">7.2<\/span> 2. Command auditing with sudo and shells<\/a><\/li><li><a href=\"#3_Aligning_SSH_practices_with_compliance_PCI-DSS_GDPR_KVKK\"><span class=\"toc_number toc_depth_2\">7.3<\/span> 3. Aligning SSH practices with compliance (PCI-DSS, GDPR, KVKK)<\/a><\/li><\/ul><\/li><li><a href=\"#Putting_It_All_Together_on_a_dchostcom_VPS\"><span class=\"toc_number toc_depth_1\">8<\/span> Putting It All Together on a dchost.com VPS<\/a><ul><li><a href=\"#Step_1_Create_a_security_baseline\"><span class=\"toc_number toc_depth_2\">8.1<\/span> Step 1: Create a security baseline<\/a><\/li><li><a href=\"#Step_2_Standardize_SSH_key_generation\"><span class=\"toc_number toc_depth_2\">8.2<\/span> Step 2: Standardize SSH key generation<\/a><\/li><li><a href=\"#Step_3_Implement_a_simple_inventory_and_automation\"><span class=\"toc_number toc_depth_2\">8.3<\/span> Step 3: Implement a simple inventory and automation<\/a><\/li><li><a href=\"#Step_4_Set_up_roles_and_groups\"><span class=\"toc_number toc_depth_2\">8.4<\/span> Step 4: Set up roles and groups<\/a><\/li><li><a href=\"#Step_5_Plan_for_rotation_revocation_and_logging\"><span class=\"toc_number toc_depth_2\">8.5<\/span> Step 5: Plan for rotation, revocation and logging<\/a><\/li><li><a href=\"#Step_6_Gradually_adopt_advanced_options\"><span class=\"toc_number toc_depth_2\">8.6<\/span> Step 6: Gradually adopt advanced options<\/a><\/li><\/ul><\/li><li><a href=\"#Conclusion_Calm_Predictable_SSH_Access_for_Your_Team\"><span class=\"toc_number toc_depth_1\">9<\/span> Conclusion: Calm, Predictable SSH Access for Your Team<\/a><\/li><\/ul><\/div>\n<h2><span id=\"Why_SSH_Key_Management_Matters_So_Much_for_Small_Teams\">Why SSH Key Management Matters So Much for Small Teams<\/span><\/h2>\n<p>SSH key management sounds like a detail until you try to answer three questions during a security review or client audit:<\/p>\n<ul>\n<li>Exactly <strong>who<\/strong> can SSH into which servers right now?<\/li>\n<li>Can we <strong>revoke<\/strong> a person\u2019s access in minutes if they leave the company?<\/li>\n<li>Can we prove <strong>which user<\/strong> executed a risky command (for example, a database drop) on a specific day?<\/li>\n<\/ul>\n<p>On a single VPS with one admin, it\u2019s easy: there\u2019s one key pair and one user. But as soon as you have 3\u201310 people touching production, the risk increases quickly:<\/p>\n<ul>\n<li>Shared root passwords and shared SSH keys make it impossible to attribute actions.<\/li>\n<li>Forgotten keys (from ex-employees or old laptops) remain on the server forever.<\/li>\n<li>Unencrypted private keys end up on developer machines, backups or cloud storage.<\/li>\n<li>Quick \u201ctemporary\u201d workarounds (like copying a key to every server manually) stay forever.<\/li>\n<\/ul>\n<p>The good news: with a few conventions and some discipline, you can build a clean SSH architecture that scales from one VPS to dozens of servers. If you haven\u2019t done basic hardening yet, it\u2019s worth pairing this article with our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-sunucu-guvenligi-nasil-saglanir-kapiyi-acik-birakmadan-yasamanin-sirri\/\">how to secure a VPS server without leaving the door open<\/a>.<\/p>\n<h2><span id=\"Core_Building_Blocks_Users_Groups_and_SSH_Keys\">Core Building Blocks: Users, Groups and SSH Keys<\/span><\/h2>\n<h3><span id=\"1_One_Linux_user_per_human_no_shared_accounts\">1. One Linux user per human \u2013 no shared accounts<\/span><\/h3>\n<p>The foundation of sane SSH access is simple: <strong>every person gets their own user account<\/strong> on the server. Avoid generic accounts like <code>dev<\/code>, <code>admin<\/code> or <code>deploy<\/code> that multiple people use interactively.<\/p>\n<p>For a small team, a common pattern is:<\/p>\n<ul>\n<li><code>alice<\/code> \u2013 developer<\/li>\n<li><code>bob<\/code> \u2013 DevOps\/lead<\/li>\n<li><code>carol<\/code> \u2013 contractor<\/li>\n<\/ul>\n<p>Each of these users will have their own SSH keys and, if needed, their own <code>sudo<\/code> permissions. If you later need service or automation accounts (<code>deploy<\/code>, <code>backup<\/code>), keep those separate and never reuse them as human logins.<\/p>\n<h3><span id=\"2_Groups_define_what_a_person_is_allowed_to_do\">2. Groups define what a person is allowed to do<\/span><\/h3>\n<p>Instead of giving everyone full <code>sudo<\/code>, use groups to manage privilege levels. For example:<\/p>\n<ul>\n<li><code>sudo<\/code> \u2013 full root via <code>sudo<\/code><\/li>\n<li><code>web-admins<\/code> \u2013 can manage web stack (Nginx, PHP-FPM), but not system-wide settings<\/li>\n<li><code>read-only<\/code> \u2013 can view logs and configs but cannot modify them<\/li>\n<\/ul>\n<p>You can then define fine-grained rules in <code>\/etc\/sudoers.d\/<\/code>, for example:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">%web-admins ALL=(root) NOPASSWD: \/bin\/systemctl restart nginx, \/bin\/systemctl restart php-fpm\n<\/code><\/pre>\n<p>This way, you share <strong>capabilities<\/strong>, not logins. When someone joins or leaves, you add or remove them from groups instead of touching complex SSH configs.<\/p>\n<h3><span id=\"3_SSH_keys_instead_of_passwords\">3. SSH keys instead of passwords<\/span><\/h3>\n<p>For SSH login, passwords should be disabled on production servers. SSH keys are more secure and easier to manage if you do it right. In a modern setup, you should prefer:<\/p>\n<ul>\n<li><strong>Key type<\/strong>: <code>ed25519<\/code> (short, strong, fast) or <code>rsa<\/code> with at least 3072 bits.<\/li>\n<li><strong>Passphrase<\/strong>: every personal private key must be encrypted with a strong passphrase.<\/li>\n<li><strong>Per-device keys<\/strong>: each laptop\/workstation has its own key, not one key copied everywhere.<\/li>\n<\/ul>\n<p>On the server side, public keys are stored in <code>~user\/.ssh\/authorized_keys<\/code>. Each line is one key; you can add options like <code>command=<\/code>, <code>from=<\/code>, or <code>no-port-forwarding<\/code> to restrict what a key can do, which is extremely useful for deployment and automation keys.<\/p>\n<h2><span id=\"Designing_a_Secure_SSH_Access_Architecture_for_a_Small_Team\">Designing a Secure SSH Access Architecture for a Small Team<\/span><\/h2>\n<h3><span id=\"1_Basic_architecture_for_one_VPS_and_a_small_team\">1. Basic architecture for one VPS and a small team<\/span><\/h3>\n<p>Let\u2019s start with a common scenario: one production VPS at dchost.com, one staging VPS, and a small team of 3\u20135 developers.<\/p>\n<p>A clean architecture could look like this:<\/p>\n<ul>\n<li>Each person has their own Linux user on each server (<code>alice<\/code>, <code>bob<\/code>, <code>carol<\/code>).<\/li>\n<li>SSH is configured to <strong>disable password authentication<\/strong> and only allow keys.<\/li>\n<li>Members are placed into groups like <code>sudo<\/code>, <code>web-admins<\/code>, or <code>read-only<\/code> depending on their role.<\/li>\n<li>Root SSH login is disabled; admins use <code>sudo<\/code> after logging in as themselves.<\/li>\n<li>All SSH access goes through a single public IP of the VPS; optionally, you can add a bastion later.<\/li>\n<\/ul>\n<p>This already solves many problems: no shared passwords, auditable user-level access, and revoking access is as simple as disabling a user or removing their keys.<\/p>\n<h3><span id=\"2_Bastion_jump_host_for_multiple_servers\">2. Bastion (jump) host for multiple servers<\/span><\/h3>\n<p>When you grow beyond one VPS (for example, a separate database node, a job worker, or a logging server), consider a <strong>bastion host<\/strong> (also called a jump server).<\/p>\n<p>Pattern:<\/p>\n<ul>\n<li>Only the bastion VPS is exposed to the internet on port 22.<\/li>\n<li>Internal servers allow SSH only from the bastion\u2019s private or VPN network.<\/li>\n<li>Team members SSH into the bastion, then <code>ssh<\/code> from bastion to internal servers.<\/li>\n<\/ul>\n<p>With modern SSH versions, this is often implemented with <code>ProxyJump<\/code> in <code>~\/.ssh\/config<\/code> instead of manually hopping, for example:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Host bastion\n  HostName bastion.example.com\n  User alice\n\nHost db-vps\n  HostName 10.0.0.10\n  User alice\n  ProxyJump bastion\n<\/code><\/pre>\n<p>This keeps your attack surface small and centralizes SSH logging on the bastion, making audits easier. It matches nicely with an architecture where you separate databases and application servers as described in our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/veritabani-sunucusunu-uygulama-sunucusundan-ayirmak-ne-zaman-mantikli\/\">when it makes sense to separate database and application servers<\/a>.<\/p>\n<h3><span id=\"3_Root_access_model_do_you_ever_SSH_as_root\">3. Root access model: do you ever SSH as root?<\/span><\/h3>\n<p>The safest default is:<\/p>\n<ul>\n<li><strong>Disable direct root login<\/strong> over SSH (<code>PermitRootLogin no<\/code>).<\/li>\n<li>Give a small set of trusted people <code>sudo<\/code> privileges.<\/li>\n<li>Log all <code>sudo<\/code> usage, so you know who escalated to root and when.<\/li>\n<\/ul>\n<p>Some teams use a separate <code>admin<\/code> group with limited root powers and require a second factor (for example, a FIDO2 key) for full administrative tasks. We cover advanced models like this in our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vpste-ssh-guvenligi-nasil-saglamlasir-fido2-anahtarlari-ssh-ca-ve-rotasyonun-sicacik-yolculugu\/\">VPS SSH hardening with FIDO2 keys and SSH CA<\/a>, but you don\u2019t have to start there. Start with per-user logins and <code>sudo<\/code>, and slowly layer extra controls.<\/p>\n<h2><span id=\"Practical_SSH_Key_Management_Workflows\">Practical SSH Key Management Workflows<\/span><\/h2>\n<h3><span id=\"1_Standardize_how_keys_are_created\">1. Standardize how keys are created<\/span><\/h3>\n<p>Agree on a team-wide convention for generating keys. For example, on each laptop:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">ssh-keygen -t ed25519 -C &quot;alice@company-laptop-2025&quot; -f ~\/.ssh\/id_ed25519_company\n<\/code><\/pre>\n<p>Best practices:<\/p>\n<ul>\n<li>Use a descriptive comment (email + device name + year).<\/li>\n<li>Use a strong passphrase; do not leave it blank.<\/li>\n<li>Store private keys only on that device (no copying to random machines).<\/li>\n<li>Back up keys in a secure, encrypted place (for example, password manager secure file storage).<\/li>\n<\/ul>\n<p>If someone needs access from two devices (for example, office PC and laptop), generate two separate key pairs with clear comments.<\/p>\n<h3><span id=\"2_Distribute_keys_to_servers_in_a_controlled_way\">2. Distribute keys to servers in a controlled way<\/span><\/h3>\n<p>The sloppiest pattern is \u201csend me your public key on Slack\u201d and then someone pastes it into <code>authorized_keys<\/code> by hand on each VPS. It works for one server but doesn\u2019t scale and is easy to get wrong.<\/p>\n<p>Better options for small teams:<\/p>\n<ul>\n<li><strong>Configuration management<\/strong> (Ansible, Chef, etc.): keep a list of team members and their keys in a repo, and let automation update <code>authorized_keys<\/code> on every VPS when something changes.<\/li>\n<li><strong>Git + script<\/strong>: even a simple Git repo with <code>alice.pub<\/code>, <code>bob.pub<\/code> and a small script that builds <code>authorized_keys<\/code> is a huge improvement over copy-paste.<\/li>\n<li><strong>Control panel integrations<\/strong>: if you use a panel on top of your dchost.com VPS, some panels let you manage SSH keys per user and deploy them to multiple accounts.<\/li>\n<\/ul>\n<p>If you are comfortable managing servers directly, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/kontrol-paneli-olmadan-vps-yonetimi-sadece-ssh-ile-web-sitesi-yayina-alma-rehberi\/\">running a VPS over SSH only without a control panel<\/a> shows how clean an SSH-only workflow can be when keys and users are organized.<\/p>\n<h3><span id=\"3_Keep_a_living_inventory_of_who_has_which_keys\">3. Keep a living inventory of who has which keys<\/span><\/h3>\n<p>Have a simple, private document or Git repo that answers:<\/p>\n<ul>\n<li>Which team members exist and what their Linux usernames are.<\/li>\n<li>Which SSH public keys are associated with each person and each device.<\/li>\n<li>Which servers they should have access to (production, staging, dev, jump host).<\/li>\n<\/ul>\n<p>For a small team, this can be a YAML or JSON file in a private Git repository that is used by your automation to generate <code>authorized_keys<\/code>. The key is that you don\u2019t rely on manually opening <code>authorized_keys<\/code> on each VPS to discover who has access.<\/p>\n<h3><span id=\"4_Key_rotation_and_offboarding_workflow\">4. Key rotation and offboarding workflow<\/span><\/h3>\n<p>Two critical moments in a key\u2019s life are <strong>rotation<\/strong> and <strong>revocation<\/strong>:<\/p>\n<ul>\n<li><strong>Rotation<\/strong>: regularly generating new keys and replacing old ones (for example, annually or when a laptop is replaced).<\/li>\n<li><strong>Revocation<\/strong>: removing keys immediately when someone leaves the team or loses a device.<\/li>\n<\/ul>\n<p>For offboarding, your runbook could be:<\/p>\n<ol>\n<li>Disable the user in your inventory (mark <code>active: false<\/code>).<\/li>\n<li>Run your automation to update all <code>authorized_keys<\/code> files.<\/li>\n<li>Optionally lock the Linux user (<code>usermod -L<\/code>) or delete it after backups\/logs are safe.<\/li>\n<li>Review logs for the last few days to ensure no suspicious activity.<\/li>\n<\/ol>\n<p>For rotation, schedule a recurring reminder every 6\u201312 months: team members generate new keys, you update the inventory, deploy new keys, and remove old ones after a short overlap. Our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vpste-secrets-yonetimi-nasil-tatli-tatli-cozulur-sops-age-gitops-akisi-systemd-ve-rotasyon\/\">secrets management on a VPS with rotation you can sleep on<\/a> has patterns that apply nicely to SSH key rotation as well.<\/p>\n<h2><span id=\"Access_Sharing_Without_Chaos_Contractors_Deployments_and_Service_Accounts\">Access Sharing Without Chaos: Contractors, Deployments and Service Accounts<\/span><\/h2>\n<h3><span id=\"1_Give_contractors_their_own_users_with_an_expiry_plan\">1. Give contractors their own users \u2013 with an expiry plan<\/span><\/h3>\n<p>Contractors and freelancers should get the same treatment as full-time staff: their own Linux user, their own SSH keys, and clear group memberships. The difference is that you also set:<\/p>\n<ul>\n<li>A clear <strong>end date<\/strong> for their access.<\/li>\n<li>A checklist item in your project management tool to remove their keys and user.<\/li>\n<\/ul>\n<p>Never share a permanent internal account (for example, <code>deploy<\/code>) with a contractor for interactive work. If you need them to perform automated deployments, give them a separate deployment key with restricted permissions instead.<\/p>\n<h3><span id=\"2_Deployment_keys_and_restricted_commands\">2. Deployment keys and restricted commands<\/span><\/h3>\n<p>For CI\/CD systems, you usually don\u2019t want full shell access. Instead, you want an SSH key that can run exactly one or a few commands (for example, a deploy script) and nothing else.<\/p>\n<p>This is where <strong>authorized_keys options<\/strong> shine. For example, a line might look like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">command=&quot;\/usr\/local\/bin\/deploy-app.sh&quot;,no-pty,no-port-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... deploy@ci\n<\/code><\/pre>\n<p>That key can only run <code>deploy-app.sh<\/code>, cannot open an interactive shell, and cannot tunnel to other ports. This is perfect for CI pipelines, Git hooks or scheduled jobs. Combined with a non-privileged <code>deploy<\/code> user and carefully scoped <code>sudo<\/code> rights, you get safe, automated deployments without risky shared admin accounts.<\/p>\n<h3><span id=\"3_Read-only_access_for_audits_and_troubleshooting\">3. Read-only access for audits and troubleshooting<\/span><\/h3>\n<p>Sometimes you want someone (support engineer, auditor, external consultant) to see logs and configs but not change anything. Instead of trusting them to \u201cbe careful\u201d, create a dedicated <code>readonly<\/code> group:<\/p>\n<ul>\n<li>Give it access to log directories and configuration files (via Unix permissions).<\/li>\n<li>Do <strong>not<\/strong> add it to <code>sudo<\/code>.<\/li>\n<li>Create a user like <code>audit-alice<\/code> or grant a contractor <code>carol<\/code> read-only membership.<\/li>\n<\/ul>\n<p>When their work is done, you remove them from the group or remove the user entirely. No need to change passwords or re-roll anything else.<\/p>\n<h2><span id=\"Advanced_Options_FIDO2_Keys_SSH_Certificates_and_Bastions\">Advanced Options: FIDO2 Keys, SSH Certificates and Bastions<\/span><\/h2>\n<h3><span id=\"1_FIDO2_hardware_keys_for_high-value_servers\">1. FIDO2 hardware keys for high-value servers<\/span><\/h3>\n<p>For sensitive environments (for example, payment data, production databases), relying only on a software-based SSH private key may feel risky. FIDO2\/U2F security keys provide hardware-backed keys that never leave the device; SSH supports these via <code>sk-ecdsa-ed25519@openssh.com<\/code> and similar key types.<\/p>\n<p>In practice, this means:<\/p>\n<ul>\n<li>Developers enroll a FIDO2 key and generate SSH keys tied to it.<\/li>\n<li>Even if someone steals the laptop, they still need the physical security key to authenticate.<\/li>\n<li>Some organizations combine this with traditional keys: FIDO2 for production, software keys for staging\/dev.<\/li>\n<\/ul>\n<p>We explain how to roll this out step-by-step in our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vpste-ssh-guvenligi-nasil-saglamlasir-fido2-anahtarlari-ssh-ca-ve-rotasyonun-sicacik-yolculugu\/\">VPS SSH security with FIDO2 keys and SSH CA<\/a>, including practical advice on user training and fallback plans.<\/p>\n<h3><span id=\"2_SSH_certificate_authority_SSH_CA_for_centralized_trust\">2. SSH certificate authority (SSH CA) for centralized trust<\/span><\/h3>\n<p>SSH certificates sound scary, but for teams with more than a handful of servers they can dramatically simplify access management:<\/p>\n<ul>\n<li>Instead of copying public keys to every server, you run a small internal SSH CA.<\/li>\n<li>Each user still has a key pair, but they get a <strong>short-lived certificate<\/strong> signed by the CA.<\/li>\n<li>Servers trust the CA; if you revoke a user at the CA level, they can no longer log in anywhere.<\/li>\n<\/ul>\n<p>This works especially well with bastion hosts: users authenticate to the bastion using certificates, and the bastion handles internal SSH connections. It adds complexity, so we recommend it once you have your basic key hygiene (per-user accounts, inventory, rotation) under control.<\/p>\n<h3><span id=\"3_Remote_access_from_multiple_locations_and_networks\">3. Remote access from multiple locations and networks<\/span><\/h3>\n<p>Small teams often work from home, office, and on the road. To reduce attack surface while keeping flexibility:<\/p>\n<ul>\n<li>Use a VPN or private overlay network (for example, WireGuard-based solutions) for SSH where possible.<\/li>\n<li>Restrict SSH access on internet-facing VPSes to specific IP ranges or VPN networks when feasible.<\/li>\n<li>Avoid long-lived agent forwarding; instead, use <code>ProxyJump<\/code> and short-lived keys or certificates.<\/li>\n<\/ul>\n<p>On dchost.com VPS or <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>s, you can dedicate one server as a secure bastion\/VPN endpoint and keep others firewalled from the public internet, connecting only over private networks.<\/p>\n<h2><span id=\"Logging_Auditing_and_Compliance-Friendly_SSH_Usage\">Logging, Auditing and Compliance-Friendly SSH Usage<\/span><\/h2>\n<h3><span id=\"1_System_logs_who_logged_in_and_from_where\">1. System logs: who logged in and from where<\/span><\/h3>\n<p>On most Linux distributions, SSH logs go to <code>\/var\/log\/auth.log<\/code> or <code>\/var\/log\/secure<\/code>. Even without any fancy tooling, you can see:<\/p>\n<ul>\n<li>Which user logged in.<\/li>\n<li>From which IP address.<\/li>\n<li>When the session started and ended.<\/li>\n<\/ul>\n<p>For small teams, make it a habit to review these logs during security reviews or after suspicious events. Better yet, send them to a central logging system so they don\u2019t disappear when a VPS is reinstalled. Our detailed guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-log-yonetimi-nasil-rayina-oturur-grafana-loki-promtail-ile-merkezi-loglama-tutma-sureleri-ve-alarm-kurallari\/\">centralized log management on a VPS with Grafana Loki and Promtail<\/a> shows one way to collect and retain SSH logs across multiple servers.<\/p>\n<h3><span id=\"2_Command_auditing_with_sudo_and_shells\">2. Command auditing with sudo and shells<\/span><\/h3>\n<p>For high-sensitivity environments, you may want to track not just logins but also commands. A few approaches:<\/p>\n<ul>\n<li>Use <code>sudo<\/code> extensively and review <code>\/var\/log\/auth.log<\/code> for <code>sudo<\/code> entries.<\/li>\n<li>Configure shells (for example, <code>bash<\/code>) to log history with timestamps and append-only settings.<\/li>\n<li>In extreme cases, use session recording tools or terminal multiplexers with logging.<\/li>\n<\/ul>\n<p>Be transparent with your team: explain what is logged and why. The goal is traceability and safety, not surveillance. Most developers welcome clear logs when something goes wrong; it helps everyone debug and learn.<\/p>\n<h3><span id=\"3_Aligning_SSH_practices_with_compliance_PCI-DSS_GDPR_KVKK\">3. Aligning SSH practices with compliance (PCI-DSS, GDPR, KVKK)<\/span><\/h3>\n<p>If you handle payments or personal data, regulations often require:<\/p>\n<ul>\n<li>Individual accounts (no shared logins).<\/li>\n<li>Least privilege (only necessary access).<\/li>\n<li>Revocation processes when people leave.<\/li>\n<li>Audit trails for administrative actions.<\/li>\n<\/ul>\n<p>A well-structured SSH key management system does exactly this. For e\u2011commerce sites, you can pair it with the hosting-side checklist in our article on <a href=\"https:\/\/www.dchost.com\/blog\/en\/e%e2%80%91ticarette-pci-dssi-dert-etmeden-nasil-uyumlu-kalirsin-hosting-tarafinda-gercekten-ne-yapmak-gerekir\/\">PCI DSS compliance for e\u2011commerce hosting<\/a> to cover both application and infrastructure responsibilities.<\/p>\n<h2><span id=\"Putting_It_All_Together_on_a_dchostcom_VPS\">Putting It All Together on a dchost.com VPS<\/span><\/h2>\n<p>Let\u2019s combine everything into a concrete, small-team playbook you can implement on a new dchost.com VPS or dedicated server.<\/p>\n<h3><span id=\"Step_1_Create_a_security_baseline\">Step 1: Create a security baseline<\/span><\/h3>\n<ul>\n<li>Update the OS and install basic tools.<\/li>\n<li>Create individual Linux users for each team member.<\/li>\n<li>Disable root SSH login and password authentication in <code>sshd_config<\/code>.<\/li>\n<li>Configure a firewall (for example, <code>ufw<\/code> or <code>nftables<\/code>) to limit SSH exposure.<\/li>\n<\/ul>\n<p>If you want a detailed hardening checklist, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-sunucu-guvenligi-pratik-olceklenebilir-ve-dogrulanabilir-yaklasimlar\/\">how to secure a VPS server against real-world threats<\/a> walks through step-by-step measures you can apply on dchost.com infrastructure.<\/p>\n<h3><span id=\"Step_2_Standardize_SSH_key_generation\">Step 2: Standardize SSH key generation<\/span><\/h3>\n<ul>\n<li>Agree on key types (for example, <code>ed25519<\/code>) and naming conventions.<\/li>\n<li>Ensure all private keys are passphrase-protected.<\/li>\n<li>Document how to back up keys securely.<\/li>\n<\/ul>\n<h3><span id=\"Step_3_Implement_a_simple_inventory_and_automation\">Step 3: Implement a simple inventory and automation<\/span><\/h3>\n<ul>\n<li>Create a private Git repo with a list of users, their keys, and their allowed servers.<\/li>\n<li>Write a small script or Ansible playbook to build and deploy <code>authorized_keys<\/code> for each user.<\/li>\n<li>Use this repo as the single source of truth during onboarding and offboarding.<\/li>\n<\/ul>\n<h3><span id=\"Step_4_Set_up_roles_and_groups\">Step 4: Set up roles and groups<\/span><\/h3>\n<ul>\n<li>Define groups like <code>sudo<\/code>, <code>web-admins<\/code>, <code>readonly<\/code>.<\/li>\n<li>Translate your team\u2019s roles (DevOps, backend, contractor) into group memberships.<\/li>\n<li>Document who can change what on production vs staging.<\/li>\n<\/ul>\n<h3><span id=\"Step_5_Plan_for_rotation_revocation_and_logging\">Step 5: Plan for rotation, revocation and logging<\/span><\/h3>\n<ul>\n<li>Set an annual or semi-annual key rotation policy.<\/li>\n<li>Write a short offboarding runbook (remove keys, groups, and possibly users).<\/li>\n<li>Ship SSH logs to a central log system; set simple alerts for unusual patterns.<\/li>\n<\/ul>\n<h3><span id=\"Step_6_Gradually_adopt_advanced_options\">Step 6: Gradually adopt advanced options<\/span><\/h3>\n<ul>\n<li>Add a bastion host if you grow beyond one or two VPSes.<\/li>\n<li>Introduce FIDO2 keys for production access.<\/li>\n<li>Consider SSH certificates when the number of servers or team members increases.<\/li>\n<\/ul>\n<p>You don\u2019t need to implement everything on day one. Start with individual accounts and properly managed <code>authorized_keys<\/code> files. As your projects grow, you can layer on more advanced controls without having to redesign everything from scratch.<\/p>\n<h2><span id=\"Conclusion_Calm_Predictable_SSH_Access_for_Your_Team\">Conclusion: Calm, Predictable SSH Access for Your Team<\/span><\/h2>\n<p>SSH key management doesn\u2019t need expensive tools or a dedicated security department. With a handful of clear decisions\u2014per-user accounts, grouped privileges, a simple key inventory, and a rotation\/offboarding process\u2014you can turn your VPS login story from \u201cI hope it\u2019s fine\u201d into \u201cwe know exactly who can do what, and we can change it in minutes\u201d.<\/p>\n<p>For small teams building on dchost.com VPS, dedicated or colocation servers, this kind of architecture is the difference between firefighting and calm operations. It fits nicely with the other pieces of a healthy stack: solid backups, monitoring, and secure deployment pipelines. If you want to go deeper, explore our articles on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-sunucu-guvenligi-nasil-saglamlasir-kapiyi-acik-birakmadan-yasamanin-sirri\/\">practical VPS security hardening<\/a>, <a href=\"https:\/\/www.dchost.com\/blog\/en\/vpste-ssh-guvenligi-nasil-saglamlasir-fido2-anahtarlari-ssh-ca-ve-rotasyonun-sicacik-yolculugu\/\">advanced SSH hardening with FIDO2 and SSH CA<\/a>, and <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-log-yonetimi-nasil-rayina-oturur-grafana-loki-promtail-ile-merkezi-loglama-tutma-sureleri-ve-alarm-kurallari\/\">centralized log management for VPS environments<\/a>.<\/p>\n<p>If you\u2019re planning your next project or consolidating existing servers, our team at dchost.com can help you choose the right VPS or dedicated setup and design a secure SSH access model from day one. Start with a single well-structured server, and you\u2019ll be ready to scale your infrastructure\u2014and your team\u2014without losing control over who holds the keys.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>When a small team starts managing one or more VPS servers, SSH access is usually the first thing that gets messy. Developers share a single root password \u201cjust for now\u201d, contractors get shell access without an expiry date, old colleagues keep their keys on the server for years, and nobody is 100% sure who can [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3518,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-3517","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3517","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=3517"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3517\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/3518"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=3517"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=3517"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=3517"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}