npm package: @ideadesignmedia/ftp
Description: Run an explicit FTPS server on Windows using environment variables loaded from `config.json`.
Latest version: 1.0.3

# FTPS Server on Windows (ftp-srv + @ideadesignmedia/config.js)

Run an explicit FTPS server on Windows using environment variables loaded from `config.json`.

## Files

```
your-project/
  ├─ index.js
  ├─ config.json
  └─ ftproot/        (your exposed root; inside you can link drives C, D, E)
```

### index.js
```js
require("@ideadesignmedia/config.js");
require("@ideadesignmedia/ftp");
```

> `@ideadesignmedia/config.js` loads `config.json` into `process.env`.  
> `@ideadesignmedia/ftp` starts the FTP server using those env vars.

---

## Example config.json

Use values similar to yours, but not identical. Adjust paths and IPs for your machine.

```json
{
  "FTPPORT": "21",
  "FTPIP": "203.0.113.25",
  "PASV_MIN": "50000",
  "PASV_MAX": "50050",
  "FTPUSERNAME": "siteuser",
  "FTPPASSWORD": "ChangeMe!42",
  "FTPPATH": "C:/ftproot",
  "FTPBLACKLIST": ["node_modules", ".git"],
  "FTPWHITELIST": ["uploads", "downloads"],

  "PRIV": "C:/ftps/ftp.key",
  "PUB": "C:/ftps/ftp.crt"

  // Or use PFX:
  // "PFX": "C:/ftps/ftps.pfx",
  // "PFX_PASS": "changeThisPass"
}
```

- `FTPPORT` 21 with `tls` enabled means explicit FTPS (client must use AUTH TLS).  
- `FTPIP` should be your public IP for internet clients or your LAN IP for local testing.  
- `PASV_MIN` and `PASV_MAX` must be opened in Windows Firewall and forwarded on your router if used over the internet.  
- `FTPPATH` is the server root that users will see on login.

---

## Expose multiple drives in FTPS

Create a single root and link drives into it. Run PowerShell as Administrator.

```powershell
New-Item -Path 'C:\ftproot' -ItemType Directory -Force

New-Item -ItemType SymbolicLink -Path 'C:\ftproot\C' -Target 'C:\'
New-Item -ItemType SymbolicLink -Path 'C:\ftproot\D' -Target 'D:\'
New-Item -ItemType SymbolicLink -Path 'C:\ftproot\E' -Target 'E:\'
```

Or via CMD:

```powershell
cmd /c mklink /D "C:\ftproot\C" "C:\"
cmd /c mklink /D "C:\ftproot\D" "D:\"
cmd /c mklink /D "C:\ftproot\E" "E:\"
```

---

## Generate TLS certificate

### Option A: OpenSSL
```powershell
openssl req -newkey rsa:2048 -nodes -keyout C:\ftps\ftp.key -x509 -days 365 -out C:\ftps\ftp.crt
```

### Option B: PowerShell PFX
```powershell
$cert = New-SelfSignedCertificate -DnsName "your.domain.example" -CertStoreLocation "Cert:\LocalMachine\My" -KeyExportPolicy Exportable -NotAfter (Get-Date).AddYears(1)
$pwd  = ConvertTo-SecureString "changeThisPass" -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath "C:\ftps\ftps.pfx" -Password $pwd
```

---

## Windows Firewall rules

```powershell
New-NetFirewallRule -DisplayName "FTPS control 21" -Direction Inbound -Protocol TCP -LocalPort 21 -Action Allow
New-NetFirewallRule -DisplayName "FTPS passive 50000-50050" -Direction Inbound -Protocol TCP -LocalPort 50000-50050 -Action Allow
```

---

## Client settings

- Protocol: FTP  
- Encryption: Require explicit FTP over TLS  
- Host: your public IP or LAN IP  
- Port: 21  
- Transfer Mode: Passive  
- Username and password from `config.json`  
- Accept the certificate warning if self-signed  

---

## Run

```bash
node index.js
```

You should see something like:

```
[FTPS] TLS enabled with key/cert or pfx
FTP Enabled
```

---

## Troubleshooting

- Plain FTP works but FTPS fails → check key/cert paths and client encryption mode.  
- 502 command not supported → client using SFTP or implicit FTPS instead of explicit.  
- Data connection fails → open firewall/forward passive ports, and ensure `FTPIP` matches your public IP.