Windows IIS Installation
This page describes how to install the Ed-Fi Admin App on Windows using Internet Information Services (IIS). It covers the backend API and the frontend single-page application.
This is one of three alternative installation paths. If you instead want to run the Admin App in containers or on a Unix-like server, see Docker Compose Installation or Unix-like Systems Installation.
Windows Prerequisites
- IIS with URL Rewrite Module: Install from Microsoft
- Node.js: Download from nodejs.org
- PostgreSQL or SqlServer: Install and configure database server
- Create an empty database, our example will use the name
sbaa
- Create an empty database, our example will use the name
- IISNode: For running Node.js applications in IIS
- An Identity Provider (IdP): For more details see Configuring an Identity Provider for Ed-Fi Admin App
- Yopass: We recommend to use this in order to share secrets correctly. For more details see Yopass Administrator Guide
Backend API Installation
You can deploy the Node.js backend directly to IIS using only iisnode. This approach is simpler but requires a slightly different configuration.
Prerequisites for Direct IIS Deployment
- IIS with iisnode: Install iisnode from GitHub Releases
- PostgreSQL or SqlServer: Install and configure database server
- Create an empty database, our example will use the name
sbaa
- Create an empty database, our example will use the name
- Node.js: Install Node.js on the server
- An Identity Provider (IdP): We use Keycloak. For more details see Configuring an Identity Provider for Ed-Fi Admin App
- Yopass: We recommend to use this in order to share secrets correctly. For more details see Yopass Administrator Guide
Steps for Direct Deployment
-
Install iisnode only:
- Download the latest iisnode installer from GitHub
- Run the installer to integrate iisnode with IIS
-
Build the application:
noteAlways install from a stable release tag, not the default
mainbranch (which reflects active development). Visit the Releases page to find the latest stable release tag, then use it in the command below.# Replace the TAG value with the latest release from the Releases page$TAG = "v4.0.1"git clone --branch $TAG --depth 1 https://github.com/Ed-Fi-Alliance-OSS/Ed-Fi-AdminApp.gitcd Ed-Fi-AdminAppnpm cinpm run build:api -
Create a folder for the website:
We recommend creating a new folder for your app. Typically IIS uses the path
C:\inetpubfor this purpose so create a folder calledC:\inetpub\EdFi-AdminApp-APIand move the following files into it:main.jsfile andassetsfolder located in folderdist/packages/api/node_modulesfolder located in source code after running thenpm cicommand- Create a folder
packages/api/configand copy the filedefault.jslocated in folderpackages/api/configfrom your source to the new folder
-
Create IIS Website:
- Open IIS Manager
- Right-click on "Sites" and choose "Add Website"
- Set Site name:
EdFi-AdminApp-API - Set Physical path: Point to your built application directory (eg.
C:\inetpub\EdFi-AdminApp-API) - Set Port: 3333 (or your preferred port)
- Important: Leave Host name blank for localhost testing, or set it only if you have proper DNS setup
-
Configure web.config for Direct IIS Deployment: Create a
web.configfile in the same directory as yourmain.jsfile:<?xml version="1.0" encoding="utf-8"?><configuration><system.webServer><!-- URL Rewrite rules - CRITICAL for proper routing --><rewrite><rules><rule name="NodeJS" stopProcessing="true"><match url=".*"/><conditions logicalGrouping="MatchAll"><add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/><add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/></conditions><action type="Rewrite" url="main.js"/></rule></rules></rewrite><!-- iisnode configuration --><iisnodenodeProcessCommandLine="node.exe"watchedFiles="web.config;*.js"loggingEnabled="true"logDirectory="iisnode"debuggingEnabled="true"devErrorsEnabled="true"node_env="production"promoteServerVars="PORT"maxConcurrentRequestsPerProcess="1024"maxNamedPipeConnectionRetry="100"namedPipeConnectionRetryDelay="250"maxNamedPipeConnectionPoolSize="512"maxNamedPipePooledConnectionAge="30000"asyncCompletionThreadCount="0"initialRequestBufferSize="4096"maxRequestBufferSize="65536"uncFileChangesPollingInterval="5000"gracefulShutdownTimeout="60000"recycleSignalEnabled="false"idlePageOutTimePeriod="0"configOverrides="iisnode.yml" /><!-- Default document --><defaultDocument><files><clear /><add value="main.js" /></files></defaultDocument><!-- Error pages for detailed debugging --><httpErrors errorMode="Detailed"/></system.webServer><system.web><compilation debug="true"/></system.web></configuration>Key Configuration Notes:
- URL Rewrite Rules: Essential for routing API requests (like
/api/*) to your Node.js application - Handler Mappings: Configure these in IIS Manager, not in web.config (due to security restrictions)
- Node.js Path: Use
node.exeto let IIS find Node.js in the system PATH - Environment: Set
node_env="development"for easier debugging, change to"production"for live deployments - configOverrides: This section allow you to have a separated file to override you
iisnodeconfiguration. For more info. Create a fileiisnode.ymlin the folder root. Eg:
loggingEnabled: truedebuggingEnabled: truedevErrorsEnabled: truenode_env: production - URL Rewrite Rules: Essential for routing API requests (like
-
Configure Handler Mappings in IIS Manager:
Since handler configuration in web.config may be restricted by IIS security policies, configure handlers through IIS Manager:
- Open IIS Manager as Administrator
- Navigate to your website
- Double-click "Handler Mappings"
- Click "Add Module Mapping..."
- Configure:
- Request path:
* - Module: Select
iisnode - Executable: empty
- Name:
iisnode-all - Click on
Request restrictions...button and then UncheckInvoke handler only if request is mapped to: File or Folderin theMappingtab. ClickOkbutton to save nad close this window. - Click
Okto close and save.
- Request path:
- Move this handler to the top of the list (above StaticFile handler)
-
Environment Configuration: Create
packages/api/config/production.jswith your settings.noteYou can also use the template located in the source code
Ed-Fi-AdminApp/packages/api/config/production.js-edfias an example// This the frontend URL we will create in the 'Frontend Installation' section, in this guide we will use http://localhost:4200, change it in case you will use a different port or hostconst FE_URL = 'http://localhost:4200';module.exports = {DB_ENGINE: 'pgsql',// 'pgsql' or 'mssql'DB_TRUST_CERTIFICATE: false, // For MSSQL local development using self-signed certs, set to trueDB_TTL_IN_MINUTES: 120, // Time to live for DB sessions in minutesDB_SSL: false, //set true if your database server support SSLDB_SECRET_VALUE: {// If you are using DB_ENGINE:'pgsql' set the following valuesDB_USERNAME: 'your_db_user',DB_PASSWORD: 'your_db_password',DB_HOST: 'localhost',DB_PORT: 5432,DB_DATABASE: 'sbaa', //The database must exist in the server// If you are using DB_ENGINE:'mssql' set the following valuesMSSQL_DB_HOST: 'edfiadminapp-mssql',MSSQL_DB_PORT: 1433,MSSQL_DB_USERNAME: 'sa',MSSQL_DB_DATABASE: 'sbaa', //The database must exist in the serverMSSQL_DB_PASSWORD: 'YourStrong!Passw0rd',},DB_ENCRYPTION_SECRET_VALUE: {// Can replace with `openssl rand -hex 32` or `node -e "console.log('KEY: '+ require('crypto').randomBytes(32).toString('hex'))"`KEY: 'your-32-char-encryption-key'},USE_YOPASS: true, //If true, you must provide the YOPASS_URLYOPASS_URL: 'http://your-yopass-site',AUTH0_CONFIG_SECRET_VALUE: {ISSUER: 'https://your-keycloak-server/auth/realms/edfi',CLIENT_ID: 'edfiadminapp',CLIENT_SECRET: 'your-client-secret',MACHINE_AUDIENCE: 'edfiadminapp-api'},//Identity provider (Idp) informationSAMPLE_OIDC_CONFIG: {issuer: 'https://your-keycloak-server/realms/edfi',clientId: 'edfiadminapp',clientSecret: 'your-client-secret',scope: '',},// If your IdP has enabled PCKE, set to trueUSE_PKCE: true,//this should match with a user in your IdPADMIN_USERNAME: 'admin@example.com',FE_URL: FE_URL,// The site you have create in the '4. Create IIS Website' stepMY_URL: 'http://localhost:3333',// The port must be match with the port you have set for the siteAPI_PORT: process.env.PORT || 3333,WHITELISTED_REDIRECTS: [FE_URL],// The time to live in millisecondsRATE_LIMIT_TTL: 60000,// The maximum number of requests within the ttlRATE_LIMIT_LIMIT: 10,}; -
Set IIS Application Pool:
- In IIS Manager, go to Application Pools
- Find your application pool (usually named after your site, in our case
EdFi-AdminApp-API) - Set .NET CLR version to "No Managed Code"
- Set Identity to an account with appropriate permissions
- Set Start Mode to "AlwaysRunning" for better performance
-
Create Required Directories:
- Create the iisnode log directory. In our case
C:\inetpub\EdFi-AdminApp-API\iisnode - Grant full permissions to the IIS App Pool user. In our case
IIS APPPOOL\EdFi-AdminApp-API
noteEnsure your IIS directory has:
C:\inetpub\EdFi-AdminApp-API\├── assets (the built folder)├── main.js (the built file)├── web.config├── iisnode.yml (optional)├── node_modules\ (complete folder after running the `npm ci` command in source code)├── packages\api\config (with your config files production.js and default.js)└── iisnode\ (log directory) - Create the iisnode log directory. In our case
Critical Success Factors
URL Rewrite Rules are Essential: The <rewrite> section in web.config is critical for proper routing. Without these rules:
- API requests like
/api/*will return 404 errors - IIS will try to serve requests as static files instead of routing them to Node.js
- The Node.js application won't receive dynamic requests
Handler Order Matters: When configuring handlers in IIS Manager, ensure the iisnode handler with path * is at the top of the handler mappings list, above the StaticFile handler.
See Troubleshooting section in case you have errors.
Frontend Installation
-
We will need to build the frontend, to do so go to
packages/fefolder of your source code, copy or rename the file.copyme.env.localto create.envand modify the values depending on your environment. This is an example:VITE_API_URL=http://localhost:3333VITE_OIDC_ID=1VITE_BASE_PATH="/"VITE_HELP_GUIDE=https://docs.ed-fi.org/reference/admin-appVITE_STARTING_GUIDE=https://docs.ed-fi.org/reference/admin-app/configuration/global-administration-tasksVITE_CONTACT=https://community.ed-fi.org/VITE_APPLICATION_NAME="Ed-Fi Admin App"VITE_IDP_ACCOUNT_URL=https://localhost/auth/realms/edfi/account/Environment Variable Descriptions:
VITE_API_URL: Backend API endpointVITE_OIDC_ID: OpenID Connect configuration ID from databaseVITE_HELP_GUIDE: URL to general help documentationVITE_STARTING_GUIDE: URL to getting started/system administrator guideVITE_CONTACT: URL to community support or contact pageVITE_APPLICATION_NAME: Display name shown in the UI (customize for branding)VITE_IDP_ACCOUNT_URL: Identity provider account management page URL
noteImportant: The
VITE_IDP_ACCOUNT_URLvalue may differ from your Keycloak admin console URL. This should point to the account management interface (/realms/{realm-name}/account/), not the admin console. Ensure this matches your actual Keycloak realm configuration and domain. -
Build the frontend:
# Go to the cloned foldercd Ed-Fi-AdminApp# Build the frontendnpm run build:fe -
Create a folder for the website:
We recommend creating a new folder for your app. Typically IIS uses the path
C:\inetpubfor this purpose so create a folder calledC:\inetpub\EdFi-AdminApp-FEand move the following files into it:index.htmlfile andassetsfolder located in folderdist/packages/fe/
-
Create IIS Website:
- Open IIS Manager
- Right-click on "Sites" and choose "Add Website"
- Set Site name:
EdFi-AdminApp-FE - Set Physical path: Point to your built application directory (eg.
C:\inetpub\EdFi-AdminApp-FE) - Set Port: 4200 (or your preferred port)
- Important: Leave Host name blank for localhost testing, or set it only if you have proper DNS setup
- Configure IIS site with proper bindings (HTTPS recommended)
-
Configure URL Rewrite for React Router:
Create a
web.configfile in the path (eg.C:\inetpub\EdFi-AdminApp-FE) with the following content:<?xml version="1.0" encoding="utf-8"?><configuration><system.webServer><rewrite><rules><rule name="React Routes" stopProcessing="true"><match url=".*" /><conditions logicalGrouping="MatchAll"><add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /><add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /><add input="{REQUEST_URI}" pattern="^/(api)" negate="true" /></conditions><action type="Rewrite" url="/" /></rule></rules></rewrite><staticContent><!-- Remove existing MIME types before adding to prevent duplicates --><remove fileExtension=".json" /><remove fileExtension=".woff" /><remove fileExtension=".woff2" /><mimeMap fileExtension=".json" mimeType="application/json" /><mimeMap fileExtension=".woff" mimeType="application/font-woff" /><mimeMap fileExtension=".woff2" mimeType="application/font-woff2" /></staticContent><httpCompression><dynamicTypes><add mimeType="application/json" enabled="true" /></dynamicTypes><staticTypes><add mimeType="application/javascript" enabled="true" /><add mimeType="text/css" enabled="true" /></staticTypes></httpCompression><!-- Error handling --><httpErrors errorMode="Detailed" /></system.webServer></configuration>Important: The
<remove>elements are critical to prevent duplicate MIME type errors. IIS may already have these MIME types configured at the server level.
See Troubleshooting section in case you have errors.