Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

Database Encryption at Rest and In Transit

By Kokil Thapa | Last reviewed: September 2026

Your database holds the data attackers want most: customer records, payment references, and legal documents. Encryption in transit and at rest closes two separate gaps—plaintext on stolen disks and plaintext on the wire between your app and the database server. On a recent audit of a Laravel production app in Nepal, TLS was enabled but certificate verification was off, so a man-in-the-middle on the same VPC could still read queries. This guide walks through both layers for MySQL 9.7, PostgreSQL 18, and Laravel 13 on PHP 8.3 or higher.

What Is the Difference Between Encryption at Rest and In Transit?

These two controls answer different threat models. Mixing them up is a common audit failure. Teams often enable HTTPS on the web tier and assume the database is covered. It is not.

Encryption at rest protects data stored on disk, SSD, or backup media. If someone steals a server from a Kathmandu colocation rack or downloads an unencrypted EBS snapshot, the raw bytes stay unreadable without the decryption key. Methods include cloud-managed TDE, filesystem encryption with LUKS or ZFS, and application-layer column encryption.

Encryption in transit protects data moving between your Laravel app and the database. Without TLS, any host on the network path can read SQL queries and result sets. This includes shared switches, compromised containers in the same cluster, and misconfigured VPC peering.

For teams running secure web infrastructure in Nepal, shared hosting and physical access risks make both layers essential. The Electronic Transactions Act 2063 (2008) and the Privacy Act 2075 (2018) expect reasonable safeguards for personal data. Encryption alone does not satisfy every legal requirement, but it is a baseline control auditors ask about first.

At RestDisk and BackupsLUKS / TDE / ColumnPhysical TheftStolen HDD / Leaked S3In TransitNetwork PathTLS 1.3 / mTLSInterceptionMITM / Sniffing
Encryption in transit and at rest: two layers defending against network interception and physical disk access.

How Do You Enforce TLS for MySQL and PostgreSQL Connections?

In-transit encryption must be mandatory, not opportunistic. Many PHP drivers attempt TLS but fall back to plaintext when negotiation fails. That silent downgrade defeats the entire control.

MySQL 9.7 with require-secure-transport

MySQL generates self-signed certificates at install time. Production systems should use certificates from an internal CA or Let's Encrypt. Edit my.cnf on the database server:

[mysqld]
ssl-ca=/etc/mysql/certs/ca.pem
ssl-cert=/etc/mysql/certs/server-cert.pem
ssl-key=/etc/mysql/certs/server-key.pem
require-secure-transport=ON
tls-version=TLSv1.3

The require-secure-transport=ON directive rejects any non-TLS connection. On the Laravel 13 side, your .env must verify the certificate chain:

DB_CONNECTION=mysql
DB_HOST=db.example.com
DB_PORT=3306
DB_DATABASE=legal_portal
DB_USERNAME=app_user
DB_PASSWORD="${DB_PASS}"
MYSQL_ATTR_SSL_CA=/etc/app/certs/ca.pem
MYSQL_ATTR_SSL_VERIFY_SERVER_CERT=true

Setting MYSQL_ATTR_SSL_CA without VERIFY_SERVER_CERT is a mistake I see often. Your app accepts any certificate signed by that CA, including one from an active attacker. Always verify. The official MySQL encrypted connections documentation covers the full attribute list.

PostgreSQL 18 with hostssl and verify-full

PostgreSQL controls transport security through pg_hba.conf. Change relevant entries from host to hostssl:

# TYPE  DATABASE   USER       ADDRESS         METHOD
hostssl legal_db   app_user   10.0.0.0/24     scram-sha-256
hostssl legal_db   app_user   ::/0            scram-sha-256

In postgresql.conf, enable TLS and set the minimum protocol:

ssl = on
ssl_cert_file = '/etc/postgresql/18/main/server.crt'
ssl_key_file = '/etc/postgresql/18/main/server.key'
ssl_ca_file = '/etc/postgresql/18/main/root.crt'
ssl_min_protocol_version = 'TLSv1.3'

Laravel's PDO driver respects the sslmode parameter. Use verify-full in production:

DB_CONNECTION=pgsql
DB_HOST=db.example.com
DB_PORT=5432
DB_DATABASE=legal_db
DB_OPTIONS="sslmode=verify-full;sslrootcert=/etc/app/certs/root.crt"

The weaker require mode only confirms TLS was negotiated. It does not validate the hostname. See the PostgreSQL SSL documentation for the full mode comparison. For deeper PostgreSQL setup, read our PostgreSQL for Laravel developers guide.

TLS Connection FlowLaravel AppPHP PDO DriverDatabaseMySQL / Postgres1. ClientHello2. Server Cert Chain3. Verify CN / SANReject if mismatch4. Encrypted SQLQueries travel as ciphertextPlaintext fallback blocked
Encryption in transit: Laravel verifies the server certificate before any SQL query leaves the application.

Which Encryption-at-Rest Strategy Fits Your Infrastructure?

The right at-rest approach depends on who manages your hardware and what compliance regime applies. There is no universal best option—only trade-offs that match your budget and team size.

MethodBest ForKey ManagementPerformance ImpactTypical Cost (Nepal VPS)
Cloud TDE (RDS/Azure)Managed databasesProvider KMSNegligibleRs 8,000–25,000/mo (~USD 60–185)
Filesystem (LUKS/ZFS)Self-hosted VPSOS-level keys5–10%Rs 3,000–8,000/mo (~USD 22–60)
Database-native TDEEnterprise complianceExternal HSM/KMS10–20%Rs 50,000+/mo (~USD 370+)
Application-layerSpecific PII fieldsApp secrets managerPer-query overheadDev time only

For most Laravel projects I deploy on Ubuntu 24.04 VPS instances, LUKS filesystem encryption provides the best balance. It needs no application changes. It works with any database engine. It protects backups automatically when they sit on the same encrypted volume. Cloud TDE is superior when available because key rotation and audit logging are handled by the provider.

Financial apps processing data under Nepal Rastra Bank payment-system guidelines should treat at-rest encryption as mandatory for production databases. The exact technical standard varies by license type, but unencrypted production disks fail every serious review.

Where is DB hosted?Cloud ManagedSelf-Hosted VPSBare MetalEnable Cloud TDERDS / Azure defaultLUKS + App LayerBalanced securityZFS + TDEMaximum protectionColumn enc for PIIColumn enc for PIIColumn enc for PII
Choose encryption at rest based on hosting environment, then add column encryption for sensitive PII fields.

When Should You Add Application-Layer Column Encryption?

Infrastructure encryption stops external attackers. It does not stop insiders with legitimate database access. A DBA with root credentials can still read plaintext rows. Application-layer encryption enforces separation of duties.

For legal-tech portals handling citizenship numbers, marriage certificates, or court documents, column encryption is often required. Laravel 13 supports native encrypted casting through Eloquent:

class Client extends Model
{
    protected $casts = [
        'citizenship_number' => 'encrypted',
        'court_case_details' => 'encrypted',
    ];
}

This uses AES-256-CBC with APP_KEY by default. Tying encryption to APP_KEY creates a single point of failure. Rotating the app key breaks all existing encrypted data. For production systems, use a dedicated encryption service with per-field keys stored in HashiCorp Vault or AWS Secrets Manager:

class Client extends Model
{
    public function getCitizenshipNumberAttribute($value): ?string
    {
        return $value
            ? FieldEncryptionService::decrypt('citizenship', $value)
            : null;
    }

    public function setCitizenshipNumberAttribute(?string $value): void
    {
        $this->attributes['citizenship_number'] = $value
            ? FieldEncryptionService::encrypt('citizenship', $value)
            : null;
    }
}

Encrypted columns cannot be indexed or searched efficiently. If you need to query by citizenship number, store a blinded HMAC-SHA256 hash alongside the ciphertext. Query the hash, then decrypt the match. This pattern appears frequently in Nepal legal-tech implementations where searchability and confidentiality must coexist.

On the Mijar Law Associates client portal, document metadata stays searchable while file contents remain encrypted at the storage layer. The combination of at-rest disk encryption, TLS in transit, and column-level protection for national ID fields covers the full threat model.

How Do You Manage Encryption Keys and Rotate Them Safely?

Encryption is only as strong as key management. Losing keys means permanent data loss. Leaking keys means total compromise. Treat key lifecycle as a first-class engineering task, not an afterthought.

  1. Never store keys in Git or plain .env files. Inject them at runtime from a secrets manager. On Deployer 7 pipelines I maintain, secrets are pulled from GitLab CI variables during deployment.
  2. Separate DEKs from KEKs. Data encryption keys encrypt records. Key encryption keys wrap DEKs. Rotating a KEK re-wraps DEKs without re-encrypting terabytes of data.
  3. Automate rotation on a schedule. Manual rotation fails under pressure. Schedule quarterly KEK rotation via cron or CI. Test backup restoration after every cycle.
  4. Audit every decrypt operation. Log access patterns. Alert on bulk decryption outside business hours or from unexpected IP ranges.
  5. Document recovery before you need it. When a server dies at 2 AM, nobody remembers where the KEK backup lives. Maintain runbooks and test them quarterly.

Use our password generator tool for initial key material, but store production keys only in a dedicated secrets manager. See our guides on HashiCorp Vault secrets management and AWS KMS envelope encryption for production patterns.

Master KEKVault / HSMDEK: UsersWrapped by KEKDEK: DocsWrapped by KEKDEK: PayWrapped by KEKEncrypted RowsAES-256-GCMEncrypted FilesSealed blobsRotate: Re-wrap DEKsNo full re-encryption
KEK wraps DEKs for encryption in transit and at rest, enabling safe key rotation without re-encrypting all database records.

What Compliance Rules Apply to Database Encryption in Nepal?

Technical encryption and legal compliance overlap but are not identical. Understanding both prevents you from shipping the wrong architecture to a regulated client.

The Privacy Act 2075 (2018) requires data controllers to protect personal information with appropriate security measures. Encryption is the most cited technical control in privacy impact assessments. The Act does not mandate a specific cipher or key length, but AES-256 with TLS 1.3 meets every reasonable interpretation.

For payment integrations using eSewa, Khalti, or ConnectIPS, follow each gateway's security requirements alongside NRB guidelines. Cardholder data falls under PCI DSS if you store PANs—most Nepali Laravel shops avoid this by tokenizing through the gateway. Read our PCI DSS essentials for developers if you touch card data at all.

The broader legal framework is covered in our data privacy law guide for Nepali web apps. Document your encryption choices in a data processing record. Auditors ask for this during due diligence for SaaS acquisitions and government tenders.

Server hardening complements database encryption. Follow our Ubuntu server security best practices and ensure backups are encrypted too. An unencrypted mysqldump on a plain ext4 partition negates every at-rest control on the live database.

How Do You Verify Encryption In Transit and At Rest Actually Works?

Configuration alone is insufficient. You must prove encryption is active and cannot be silently downgraded. Run these checks in CI and after every deployment.

  • TLS verification: Connect with mysql --ssl-mode=VERIFY_IDENTITY or psql "sslmode=verify-full". Connection must succeed. Retry with --ssl-mode=DISABLED; it must fail.
  • Certificate expiry monitoring: Alert 30 days before certificate expiration. Expired certs cause hard outages or silent fallback on poorly configured clients.
  • At-rest verification: For LUKS, run lsblk -o NAME,FSTYPE,TYPE and confirm crypto_LUKS. For cloud TDE, check the provider console encryption flag.
  • Column encryption test: Insert known plaintext via the app. Query directly through the MySQL CLI. Confirm ciphertext is returned, not the original value.
  • Backup encryption: Restore to an isolated environment. Confirm encryption persists on the restored volume. See our database backup strategies guide and automated backup setup.

I add these checks to every GitLab CI pipeline for legal-tech and e-commerce clients. A passing test suite that skips encryption validation gives false confidence. Make verification automatic and blocking. Our OWASP Top 10 for Laravel guide covers related application-layer controls.

For enterprise deployments needing a full security review, our enterprise application development service includes encryption architecture as part of the initial design phase—not as a post-launch patch.

Key Takeaways

  • Encryption in transit and at rest are separate controls—TLS protects the wire, LUKS or TDE protects the disk.
  • Enforce require-secure-transport=ON on MySQL and hostssl with verify-full on PostgreSQL; never allow plaintext fallback.
  • Use application-layer column encryption only for high-sensitivity fields like national IDs, not entire tables.
  • Separate DEKs from KEKs so key rotation does not require re-encrypting all data.
  • Verify encryption in CI: test TLS enforcement, check LUKS status, and confirm backups stay encrypted.
  • Map your setup to Nepal's Privacy Act 2075 and NRB payment guidelines before handling citizen or financial data.

People Also Ask

Is database encryption required by law in Nepal?

The Privacy Act 2075 (2018) requires appropriate security measures for personal data but does not specify exact algorithms. Encryption in transit and at rest is the standard interpretation of "appropriate measures" in privacy impact assessments. Payment processors must also follow NRB security guidelines.

Does Laravel encrypt database connections by default?

No. Laravel 13 passes connection options to PDO, but TLS is off unless you configure SSL attributes in .env. You must enable it on both the database server and the application side with certificate verification enabled.

What is the difference between TDE and application-layer encryption?

TDE encrypts entire database files transparently at the storage engine or filesystem level. Application-layer encryption encrypts specific columns before they reach the database. TDE protects against disk theft; column encryption protects against DBAs with full query access.

Can encrypted database columns be searched or indexed?

Not directly. Encrypted values are opaque to the database engine. Store a separate HMAC hash of the plaintext for equality lookups. Full-text search on encrypted columns requires specialized schemes like deterministic encryption, which has weaker security properties.

Start With TLS, Then Layer At-Rest Controls

Begin with in-transit TLS enforcement—it takes under an hour and closes the highest-risk gap immediately. Then assess at-rest posture based on your hosting environment. Add column encryption only where regulatory or contractual obligations demand it. Document key management before you need it at 3 AM.

If you are building systems that handle sensitive Nepali citizen data or international client information, encryption in transit and at rest should be designed in from day one—not bolted on after an audit finding. Contact us for an encryption architecture review, or reach out directly to discuss your specific requirements.

Frequently Asked Questions

Encryption at rest protects stored data files on disk using algorithms like AES-256, preventing access if physical media is stolen. Encryption in transit secures data moving between client and server via TLS/SSL, stopping network interception. Both are required for complete protection; one without the other leaves a critical vulnerability gap in your infrastructure.

Yes, expect 3-5% overhead for TLS handshakes and 1-3% for disk I/O with modern NVMe storage. On production Laravel applications I have managed, enabling MySQL TDE and enforcing TLS added negligible latency because hardware acceleration handles AES-NI instructions. The real bottleneck is usually unoptimized queries or missing indexes, not the encryption layer itself.

Configure the sslmode option in config/database.php to require or verify-ca. Ensure your MySQL server has valid certificates and the mysql user requires SSL. In my experience deploying legal-tech portals, skipping certificate verification exposes you to man-in-the-middle attacks. Always bundle the CA cert in your deployment artifacts and validate the full chain during GitLab CI pipeline tests.

No, TDE is exclusive to MySQL Enterprise Edition. Community users must rely on filesystem-level encryption like LUKS or ZFS native encryption. For budget-sensitive Nepal projects costing under Rs 500,000, I consistently recommend LUKS on Ubuntu 24 servers over expensive Enterprise licenses. It provides equivalent at-rest protection for stolen drives without recurring licensing fees.

Open-source tools like Let's Encrypt and LUKS cost zero in licensing, only engineering time. Expect Rs 30,000–60,000 (USD 225–450) for initial setup and testing by a senior developer. Enterprise TDE licenses start around USD 5,000 annually. For most Nepali SMEs, the open-source stack provides sufficient compliance and security without the enterprise price tag.

Encrypted backups require secure key management separate from the backup storage. If you lose the encryption key, the backup is permanently unrecoverable. On production systems I maintain, we store keys in HashiCorp Vault or AWS KMS, never on the same server as the database. Test restores quarterly to verify key accessibility and decryption integrity under real recovery conditions.

Yes, application-level column encryption using Laravel's Crypt facade or MySQL's AES_ENCRYPT function targets sensitive fields like PAN numbers or passwords. This avoids full-disk overhead but complicates searching and indexing encrypted columns. I use this pattern for legal document metadata where only specific case identifiers need protection while keeping general case data queryable for admin dashboards.

Encryption at rest and in transit satisfies PCI DSS requirement 3.4 and NRB IT guidelines for financial data protection. However, compliance also demands key rotation policies, access logging, and documented procedures. Merely enabling encryption without governance documentation will fail an audit. I have helped fintech clients pass NRB inspections by combining technical controls with proper operational documentation.

Use envelope encryption where data keys encrypt data and master keys encrypt data keys. Rotate master keys periodically without re-encrypting all data. For MySQL Enterprise, use the keyring plugin with dual-key support. On community editions with LUKS, add a new key slot then remove the old one. Always test rotation in staging first; I have seen production outages from untested key rotations.

All encrypted data becomes permanently inaccessible. There is no backdoor or recovery mechanism by design. Store keys in redundant, geographically separated secure locations with strict access controls. On client projects, I implement automated key backup to encrypted S3 buckets with versioning. Treat key loss prevention with the same urgency as database backup verification.

Use TLS 1.3 exclusively. SSL 2.0/3.0 and TLS 1.0/1.1 are deprecated and vulnerable. MySQL 8.4 defaults to TLS 1.3 when both sides support it. Configure your server to reject older protocols explicitly. Legacy PHP 8.2 clients may need OpenSSL 3.x updates. Never negotiate down to insecure versions for backward compatibility; upgrade the client instead.

Replication traffic between primary and replica nodes must also be encrypted via TLS. Unencrypted replication streams expose data even if storage is encrypted. Configure source and replica with matching TLS certificates and enforce secure transport. In Galera or Group Replication clusters, encrypt the group communication channel separately. I verify replication encryption status monthly using SHOW REPLICA STATUS on production systems.

Full-text search and range queries on encrypted columns are impossible without decryption. Use deterministic encryption for equality searches or maintain separate hashed indexes for lookups. For complex search needs, consider searchable encryption schemes or keep non-sensitive metadata unencrypted. On e-commerce platforms like Nepal Gift Card, we encrypt payment tokens but leave product SKUs and order dates queryable for operational reporting.

Storing keys alongside encrypted data, skipping TLS certificate validation, forgetting to encrypt backups, and neglecting key rotation testing. Another frequent error is assuming encryption replaces access controls; compromised credentials bypass encryption entirely. Implement defense in depth: encryption plus RBAC plus audit logging. Review configurations against CIS benchmarks before going live.

For transit, run tcpdump or Wireshark to confirm no plaintext SQL appears on the wire. For at-rest, inspect raw data files with hexdump to verify ciphertext. Check MySQL variables SHOW VARIABLES LIKE '%ssl%' and encryption status commands. Automate these checks in your CI pipeline. On deployments via Deployer 7, I include post-deploy verification scripts that fail the release if encryption is misconfigured.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: