How to Join Windows and Linux Machines to Active Directory Domain on Windows Server 2025
Active Directory (AD) is the identity backbone of most enterprise networks. Joining both Windows and Linux machines to the domain centralizes authentication, enforces Group Policy, enables single sign-on (SSO), and provides unified user and computer management through tools like Active Directory Users and Computers. Windows Server 2025 supports a broad range of client operating systems, and modern Linux distributions can participate in Active Directory authentication using the realmd and sssd stack — without requiring third-party products. This guide covers joining Windows servers and workstations to an AD domain via PowerShell, performing silent unattended joins with credential objects, verifying domain membership, and integrating Linux machines using realmd and SSSD, including PAM configuration and SSH access with AD credentials.
Prerequisites
- A working Active Directory domain running on Windows Server 2025 (or mixed-mode with earlier versions)
- DNS configured so client machines can resolve the domain name (e.g.,
corp.example.comresolves to a DC) - Domain Admin or delegated “Join computers to domain” permission on the account used for joining
- Windows machines: PowerShell 5.1 or later, local Administrator access
- Linux machines: a Debian/Ubuntu or RHEL/Rocky-based distribution with network access to the DC; packages
realmd,sssd,sssd-ad,krb5-user,adcli - Time synchronization on all machines — Kerberos authentication fails with clock skew over 5 minutes
Step 1: Join a Windows Server to the Domain Using PowerShell
The Add-Computer cmdlet joins a Windows machine to an Active Directory domain. When run interactively, it prompts for domain credentials. This method is appropriate when you are running the command in an interactive session on the target server.
# Join the local machine to the domain (will prompt for credentials)
Add-Computer `
-DomainName "corp.example.com" `
-OUPath "OU=Servers,OU=Corp,DC=corp,DC=example,DC=com" `
-Restart `
-Force
# Join and place the computer in a specific OU
Add-Computer `
-DomainName "corp.example.com" `
-OUPath "OU=WebServers,OU=Servers,OU=Corp,DC=corp,DC=example,DC=com" `
-NewName "WEBSVR01" `
-Restart `
-Force
The -OUPath parameter places the computer account in the specified Organizational Unit instead of the default Computers container. The -NewName parameter renames the computer as part of the join operation, which is useful when provisioning a new server with a temporary hostname.
Step 2: Silent Domain Join with a PowerShell Credential Object
For automated provisioning — such as when deploying servers via scripts, CI/CD pipelines, or configuration management tools — you should perform a silent domain join using a pre-built PSCredential object. This avoids interactive prompts while keeping the password out of the script source by reading it from a secure source such as a secrets manager or encrypted file.
# Method 1: Prompt once for credentials and store in a variable
$DomainCredential = Get-Credential -Message "Enter domain join credentials" -UserName "CORPSvcDomainJoin"
# Method 2: Build a credential object from a secure string (for automation)
# Retrieve the password from an environment variable or secret store
$SecurePass = ConvertTo-SecureString $env:DOMAIN_JOIN_PASSWORD -AsPlainText -Force
$DomainCredential = New-Object System.Management.Automation.PSCredential(
"CORPSvcDomainJoin",
$SecurePass
)
# Perform the domain join silently using the credential object
Add-Computer `
-DomainName "corp.example.com" `
-Credential $DomainCredential `
-OUPath "OU=Servers,OU=Corp,DC=corp,DC=example,DC=com" `
-NewName "APPSVR02" `
-Options JoinWithNewName, AccountCreate `
-Force `
-Restart
# Join a REMOTE machine to the domain (run from a management server)
Add-Computer `
-ComputerName "TARGETSERVER" `
-DomainName "corp.example.com" `
-Credential $DomainCredential `
-LocalCredential (Get-Credential -Message "Local admin on TARGETSERVER") `
-OUPath "OU=Servers,OU=Corp,DC=corp,DC=example,DC=com" `
-Restart `
-Force
When joining multiple machines in bulk, use the -ComputerName parameter as an array and pipe from a CSV file containing computer names and target OUs for large-scale deployments.
Step 3: Verify Windows Domain Join
After the machine restarts, verify that the domain join succeeded before proceeding. Use Get-WmiObject Win32_ComputerSystem (available in all PowerShell versions) or the newer Get-CimInstance equivalent. Also test that Kerberos authentication is working by listing domain group memberships.
# Verify domain membership using WMI
Get-WmiObject -Class Win32_ComputerSystem |
Select-Object Name, Domain, PartOfDomain, Workgroup
# Modern equivalent using CIM
Get-CimInstance -ClassName Win32_ComputerSystem |
Select-Object Name, Domain, PartOfDomain
# Test domain connectivity — list domain controllers
nltest /dsgetdc:corp.example.com
# Verify the computer account exists in AD (run from any domain-joined machine)
Get-ADComputer -Identity "APPSVR02" |
Select-Object Name, DNSHostName, DistinguishedName, Enabled
# Test Kerberos by listing the current user's group memberships
whoami /groups | Select-String "Domain"
# Check that domain users can be resolved locally
net user /domain CORPjsmith
Step 4: Install Required Packages on Linux
Linux machines use the realmd discovery and enrollment tool combined with SSSD (System Security Services Daemon) to join Active Directory and authenticate users. The exact package names vary by distribution. The following commands cover Ubuntu/Debian and RHEL/Rocky Linux.
# Run these commands in a Linux terminal as root or with sudo
# Ubuntu / Debian
# apt update && apt install -y realmd sssd sssd-ad sssd-tools
# krb5-user adcli samba-common-bin oddjob oddjob-mkhomedir packagekit
# RHEL / Rocky Linux / AlmaLinux
# dnf install -y realmd sssd sssd-ad sssd-krb5 sssd-common adcli
# samba-common-tools oddjob oddjob-mkhomedir krb5-workstation
# Verify realmd can discover the domain (DNS must resolve the domain)
# realm discover corp.example.com
# Expected output includes:
# corp.example.com
# type: kerberos
# realm-name: CORP.EXAMPLE.COM
# domain-name: corp.example.com
# configured: no
# server-software: active-directory
# client-software: sssd
The oddjob and oddjob-mkhomedir packages are essential — they automatically create home directories for domain users on their first login, so users do not encounter a missing home directory error.
Step 5: Join Linux to the Active Directory Domain with realm join
The realm join command handles the entire enrollment process: it obtains a Kerberos ticket for the specified admin account, creates a computer account in AD, and writes the SSSD configuration file. By default, the computer account is created in the Computers container; use --computer-ou to specify a different OU.
# Run in a Linux terminal — join the domain as a Domain Admin
# realm join --user=Administrator corp.example.com
# Join and place the computer in a specific OU
# realm join
# --user=Administrator
# --computer-ou="OU=LinuxServers,OU=Servers,OU=Corp,DC=corp,DC=example,DC=com"
# corp.example.com
# Verify the join succeeded
# realm list
# Expected output:
# corp.example.com
# type: kerberos
# realm-name: CORP.EXAMPLE.COM
# domain-name: corp.example.com
# configured: kerberos-member
# server-software: active-directory
# client-software: sssd
# required-package: sssd-tools
# login-formats: %[email protected]
# login-policy: allow-realm-logins
# Confirm the computer account was created in AD (from a Windows DC)
Get-ADComputer -Filter { Name -eq "ubuntu-server01" } |
Select-Object Name, DNSHostName, DistinguishedName
Step 6: Configure SSSD for Active Directory Authentication
After realm join, the file /etc/sssd/sssd.conf is automatically generated. However, reviewing and tuning this file is important for production deployments. Key settings control which AD users can log in, whether fully-qualified usernames are required, and how offline authentication behaves.
# View the auto-generated sssd.conf (from a Linux terminal)
# cat /etc/sssd/sssd.conf
# A well-tuned /etc/sssd/sssd.conf for AD integration:
# [sssd]
# domains = corp.example.com
# config_file_version = 2
# services = nss, pam
#
# [domain/corp.example.com]
# default_shell = /bin/bash
# krb5_store_password_if_offline = True
# cache_credentials = True
# krb5_realm = CORP.EXAMPLE.COM
# realmd_tags = manages-system joined-with-adcli
# id_provider = ad
# fallback_homedir = /home/%u@%d
# ad_domain = corp.example.com
# use_fully_qualified_names = False # Allow login as 'jsmith' not '[email protected]'
# ldap_id_mapping = True
# access_provider = ad
# After editing, restart SSSD and verify
# systemctl restart sssd
# systemctl status sssd
# Allow only specific AD groups to log in (optional security hardening)
# realm permit -g "[email protected]"
# realm permit -g "Domain [email protected]"
# Test that an AD user can be resolved by the OS
# id [email protected]
# id jsmith # (if use_fully_qualified_names = False)
Step 7: Configure PAM for Home Directory Creation
The Pluggable Authentication Modules (PAM) stack on Linux controls how authentication events are handled, including session setup steps like creating home directories. Enable pam_mkhomedir (via oddjob-mkhomedir) so that AD users get a home directory automatically created on their first login without manual intervention.
# Enable oddjob home directory creation (Ubuntu/Debian)
# pam-auth-update --enable mkhomedir
# Enable on RHEL/Rocky using authselect
# authselect select sssd with-mkhomedir --force
# Enable and start the oddjobd service
# systemctl enable oddjobd --now
# Verify PAM is configured correctly by checking /etc/pam.d/common-session (Debian)
# or /etc/pam.d/system-auth (RHEL) for the mkhomedir line:
# session optional pam_mkhomedir.so skel=/etc/skel umask=0077
# Test a domain user login (creates home directory on first use)
# su - [email protected]
# pwd
# ls -la ~
Step 8: Enable SSH Access with Active Directory Accounts
SSH is the primary remote access method for Linux servers. By default after domain join, AD users can authenticate via SSH using their domain password. You may want to further configure SSH to allow specific AD groups or enforce Kerberos (GSSAPI) authentication for passwordless single sign-on from Windows machines with a valid Kerberos ticket.
# Edit /etc/ssh/sshd_config to allow AD group-based access
# Add or modify these lines:
# AllowGroups [email protected] "domain [email protected]"
# GSSAPIAuthentication yes
# GSSAPICleanupCredentials yes
# UsePAM yes
# After editing sshd_config, reload SSH
# systemctl reload sshd
# From a Windows machine, test Kerberos SSH (GSSAPI — no password prompt if TGT exists)
# Ensure you have a valid Kerberos ticket first:
# klist # (in a Windows terminal — should show a TGT for corp.example.com)
# SSH to the Linux server using GSSAPI
# ssh -o GSSAPIAuthentication=yes [email protected]
# Test AD user login works from Linux console or SSH
# ssh [email protected]
# Password: [domain password]
# id # should show uid, gid, and AD group memberships
Step 9: Troubleshooting with kinit and klist
When AD authentication fails on a Linux machine, the most effective diagnostic approach is to test Kerberos ticket acquisition directly using kinit. If kinit succeeds, the Kerberos/AD layer is working and the problem lies in SSSD or PAM configuration. If kinit fails, focus on DNS resolution, time synchronization, or the domain join itself.
# Test Kerberos authentication directly (Linux terminal)
# kinit [email protected]
# Password for [email protected]: [domain password]
# View acquired tickets
# klist
# Expected output shows a ticket-granting ticket (TGT):
# Credentials cache: FILE:/tmp/krb5cc_0
# Principal: [email protected]
# ...
# Issued Expires Principal
# 05/17/2026 05/18/2026 krbtgt/[email protected]
# Destroy the ticket when done testing
# kdestroy
# Check SSSD logs for authentication failures
# journalctl -u sssd --since "1 hour ago" | grep -i "error|fail|denied"
# Check /var/log/sssd/ for domain-specific logs
# tail -f /var/log/sssd/sssd_corp.example.com.log
# Verify DNS resolution of the domain from the Linux machine
# nslookup corp.example.com
# nslookup _kerberos._tcp.corp.example.com
# Check time sync (Kerberos requires < 5 minute clock skew)
# timedatectl status
# From a Windows DC, verify the Linux computer account (run on DC)
Get-ADComputer -Filter { Name -eq "ubuntu-server01" } -Properties LastLogonDate |
Select-Object Name, Enabled, LastLogonDate, OperatingSystem
Conclusion
Integrating both Windows and Linux machines into a Windows Server 2025 Active Directory domain creates a unified, centrally managed identity platform across your entire server estate. Windows machines join the domain cleanly using the Add-Computer cmdlet, supporting both interactive and fully automated silent joins with PSCredential objects suitable for infrastructure-as-code workflows. Linux machines, through the realmd and SSSD stack, become full participants in the domain — domain users can authenticate via SSH, home directories are created automatically through PAM and oddjob, and Kerberos provides seamless single sign-on from Windows clients. When problems arise, kinit and klist quickly isolate whether the issue is at the Kerberos, SSSD, or SSH layer. With the steps in this guide, your mixed-OS environment can leverage Active Directory as the single source of truth for identity, simplifying management and strengthening security across every machine in your organization.