diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 310dedbb5fa45c22c9afd92b8a9a91849f04b1f9..2a53749a72d4c1fd2027c00b471e56256609cda4 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -118,6 +118,8 @@ const char* nulstr="";
 	int GCES_level;                                                      \
 	get_crypt_error_string(status, sess, &GCES_estr, action, &GCES_level);\
 	if (GCES_estr) {                                                       \
+		if (GCES_level < startup->ssh_error_level)							\
+			GCES_level = startup->ssh_error_level;							 \
 		lprintf(GCES_level, "Node %d SSH %s from %s", node, GCES_estr, __FUNCTION__);             \
 		free_crypt_attrstr(GCES_estr);                                       \
 	}                                                                         \
@@ -128,6 +130,8 @@ const char* nulstr="";
 	int GCES_level;                                                      \
 	get_crypt_error_string(status, sess, &GCES_estr, action, &GCES_level);\
 	if (GCES_estr) {                                                       \
+		if (GCES_level < startup->ssh_error_level)							\
+			GCES_level = startup->ssh_error_level;							 \
 		lprintf(GCES_level, "SSH %s from %s", GCES_estr, __FUNCTION__);     \
 		free_crypt_attrstr(GCES_estr);                                       \
 	}                                                                         \
@@ -138,17 +142,21 @@ const char* nulstr="";
 	int GCES_level;                                                      \
 	get_crypt_error_string(status, sess, &GCES_estr, action, &GCES_level);\
 	if (GCES_estr) {                                                       \
+		if (GCES_level < startup->ssh_error_level)							\
+			GCES_level = startup->ssh_error_level;							 \
 		lprintf(GCES_level, "%04d SSH %s from %s", sock, GCES_estr, __FUNCTION__);                \
 		free_crypt_attrstr(GCES_estr);                                       \
 	}                                                                         \
 } while (0)
 
-#define GCESSTR(status, str, log_level, sess, action) do {                         \
+#define GCESSTR(status, str, sess, action) do {                         \
 	char *GCES_estr;                                                    \
 	int GCES_level;                                                      \
 	get_crypt_error_string(status, sess, &GCES_estr, action, &GCES_level);\
 	if (GCES_estr) {                                                       \
-		lprintf(log_level, "%s SSH %s from %s (session %d)", str, GCES_estr, __FUNCTION__, sess);                \
+		if (GCES_level < startup->ssh_error_level)							\
+			GCES_level = startup->ssh_error_level;							 \
+		lprintf(GCES_level, "%s SSH %s from %s (session %d)", str, GCES_estr, __FUNCTION__, sess);                \
 		free_crypt_attrstr(GCES_estr);                                       \
 	}                                                                         \
 } while (0)
@@ -2468,7 +2476,7 @@ void output_thread(void* arg)
 				continue;
 			}
 			if (cryptStatusError((err=cryptSetAttribute(sbbs->ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, sbbs->session_channel)))) {
-				GCESSTR(err, node, LOG_WARNING, sbbs->ssh_session, "setting channel");
+				GCESSTR(err, node, sbbs->ssh_session, "setting channel");
 				ssh_errors++;
 				sbbs->online=FALSE;
 				i=buftop-bufbot;	// Pretend we sent it all
@@ -2483,7 +2491,7 @@ void output_thread(void* arg)
 					sendbytes = 0x2000;
 				if(cryptStatusError((err=cryptPushData(sbbs->ssh_session, (char*)buf+bufbot, buftop-bufbot, &i)))) {
 					/* Handle the SSH error here... */
-					GCESSTR(err, node, LOG_WARNING, sbbs->ssh_session, "pushing data");
+					GCESSTR(err, node, sbbs->ssh_session, "pushing data");
 					ssh_errors++;
 					sbbs->online=FALSE;
 					i=buftop-bufbot;	// Pretend we sent it all
@@ -2495,9 +2503,9 @@ void output_thread(void* arg)
 					 * what the current write timeout is.
 					 */
 					if(cryptStatusError(err=cryptSetAttribute(sbbs->ssh_session, CRYPT_OPTION_NET_WRITETIMEOUT, 5)))
-						GCESSTR(err, node, LOG_WARNING, sbbs->ssh_session, "setting write timeout");
+						GCESSTR(err, node, sbbs->ssh_session, "setting write timeout");
 					if(cryptStatusError((err=cryptFlushData(sbbs->ssh_session)))) {
-						GCESSTR(err, node, LOG_WARNING, sbbs->ssh_session, "flushing data");
+						GCESSTR(err, node, sbbs->ssh_session, "flushing data");
 						ssh_errors++;
 						if (err != CRYPT_ERROR_TIMEOUT) {
 							sbbs->online=FALSE;
@@ -2506,7 +2514,7 @@ void output_thread(void* arg)
 					}
 					// READ = WRITE TIMEOUT HACK... REMOVE WHEN FIXED
 					if(cryptStatusError(err=cryptSetAttribute(sbbs->ssh_session, CRYPT_OPTION_NET_WRITETIMEOUT, 0)))
-						GCESSTR(err, node, LOG_WARNING, sbbs->ssh_session, "setting write timeout");
+						GCESSTR(err, node, sbbs->ssh_session, "setting write timeout");
 				}
 			}
 			pthread_mutex_unlock(&sbbs->ssh_mutex);
diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c
index 390368f0d60683b60a939ef293faba9c59b15e04..b5cdd6705e744669eb00b2688480a32e21e2eb5b 100644
--- a/src/sbbs3/sbbs_ini.c
+++ b/src/sbbs3/sbbs_ini.c
@@ -433,6 +433,8 @@ void sbbs_read_ini(
 			=iniGetShortInt(list,section,"SSHPort",22);
 		bbs->ssh_connect_timeout
 			=iniGetShortInt(list,section,"SSHConnectTimeout",10);
+		bbs->ssh_error_level
+			=iniGetLogLevel(list, section, "SSHErrorLevel", LOG_WARNING);
 		bbs->ssh_interfaces
 			=iniGetStringList(list,section,"SSHInterface",",",global_interfaces);
 
@@ -900,6 +902,8 @@ BOOL sbbs_write_ini(
 			break;
 		if(!iniSetUInteger(lp,section,"SSHConnectTimeout",bbs->ssh_connect_timeout,&style))
 			break;
+		if(!iniSetLogLevel(lp, section, "SSHErrorLevel", bbs->ssh_error_level, &style))
+			break;
 
 		if(!iniSetUInteger(lp,section,"FirstNode",bbs->first_node,&style))
 			break;
diff --git a/src/sbbs3/scfg/scfgsrvr.c b/src/sbbs3/scfg/scfgsrvr.c
index f5172035b2d9797c8b69d19e35cfd1a942b0c8b7..90903dcfe4c0389b724de80816f2552253bb25c3 100644
--- a/src/sbbs3/scfg/scfgsrvr.c
+++ b/src/sbbs3/scfg/scfgsrvr.c
@@ -352,6 +352,7 @@ static void termsrvr_cfg(void)
 		snprintf(opt[i++], MAX_OPLN, "%-30s%u", "SSH Port", startup.ssh_port);
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "SSH Connect Timeout"
 			,startup.options & BBS_OPT_ALLOW_SSH ? vduration(startup.ssh_connect_timeout) : "N/A");
+		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "SSH Error Level", iniLogLevelStringList()[startup.ssh_error_level]);
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Telnet Support", startup.options & BBS_OPT_NO_TELNET ? "No" : "Yes");
 		snprintf(opt[i++], MAX_OPLN, "%-30s%s", "Telnet Interfaces"
 			,startup.options & BBS_OPT_NO_TELNET ? "N/A" : strListCombine(startup.telnet_interfaces, tmp, sizeof(tmp), ", "));
@@ -430,9 +431,12 @@ static void termsrvr_cfg(void)
 					startup.ssh_connect_timeout = (uint16_t)parse_duration(str);
 				break;
 			case 9:
-				startup.options ^= BBS_OPT_NO_TELNET;
+				uifc.list(WIN_MID|WIN_SAV, 0, 0, 0, &startup.ssh_error_level, 0, "SSH Error Log Level", iniLogLevelStringList());
 				break;
 			case 10:
+				startup.options ^= BBS_OPT_NO_TELNET;
+				break;
+			case 11:
 				strListCombine(startup.telnet_interfaces, str, sizeof(str), ", ");
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Telnet Network Interfaces (IPv4/6)", str, sizeof(str)-1, K_EDIT) >= 0) {
 					strListFree(&startup.telnet_interfaces);
@@ -440,21 +444,21 @@ static void termsrvr_cfg(void)
 					uifc.changes = true;
 				}
 				break;
-			case 11:
+			case 12:
 				SAFEPRINTF(str, "%u", startup.telnet_port);
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Telnet TCP Port", str, 5, K_NUMBER|K_EDIT) > 0)
 					startup.telnet_port = atoi(str);
 				break;
-			case 12:
+			case 13:
 				startup.options ^= BBS_OPT_DEBUG_TELNET;
 				break;
-			case 13:
+			case 14:
 				startup.options ^= BBS_OPT_NO_TELNET_GA;
 				break;
-			case 14:
+			case 15:
 				startup.options ^= BBS_OPT_ALLOW_RLOGIN;
 				break;
-			case 15:
+			case 16:
 				strListCombine(startup.rlogin_interfaces, str, sizeof(str), ", ");
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "RLogin Network Interfaces (IPv4/6)", str, sizeof(str)-1, K_EDIT) >= 0) {
 					strListFree(&startup.rlogin_interfaces);
@@ -462,53 +466,53 @@ static void termsrvr_cfg(void)
 					uifc.changes = true;
 				}
 				break;
-			case 16:
+			case 17:
 				SAFEPRINTF(str, "%u", startup.rlogin_port);
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "RLogin TCP Port", str, 5, K_NUMBER|K_EDIT) > 0)
 					startup.rlogin_port = atoi(str);
 				break;
-			case 17:
+			case 18:
 				SAFEPRINTF(str, "%u", startup.pet40_port);
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "40 Column CBM/PETSCII TCP Port", str, 5, K_NUMBER|K_EDIT) > 0)
 					startup.pet40_port = atoi(str);
 				break;
-			case 18:
+			case 19:
 				SAFEPRINTF(str, "%u", startup.pet80_port);
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "80 Column CBM/PETSCII TCP Port", str, 5, K_NUMBER|K_EDIT) > 0)
 					startup.pet80_port = atoi(str);
 				break;
-			case 19:
+			case 20:
 				SAFECOPY(str, maximum(startup.max_concurrent_connections));
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Concurrent (Unauthenticated) Connections", str, 10, K_EDIT) > 0)
 					startup.max_concurrent_connections = atoi(str);
 				break;
-			case 20:
+			case 21:
 				SAFECOPY(str, duration(startup.max_login_inactivity, false));
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Socket Inactivity at Login", str, 10, K_EDIT) > 0)
 					startup.max_login_inactivity = (uint16_t)parse_duration(str);
 				break;
-			case 21:
+			case 22:
 				SAFECOPY(str, duration(startup.max_newuser_inactivity, false));
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Socket Inactivity at New User Registration", str, 10, K_EDIT) > 0)
 					startup.max_newuser_inactivity = (uint16_t)parse_duration(str);
 				break;
-			case 22:
+			case 23:
 				SAFECOPY(str, duration(startup.max_session_inactivity, false));
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Maximum Socket Inactivity during User Session", str, 10, K_EDIT) > 0)
 					startup.max_session_inactivity = (uint16_t)parse_duration(str);
 				break;
-			case 23:
+			case 24:
 				SAFEPRINTF(str, "%u", startup.outbuf_drain_timeout);
 				if(uifc.input(WIN_MID|WIN_SAV, 0, 0, "Output Buffer Drain Timeout (milliseconds)", str, 5, K_NUMBER|K_EDIT) > 0)
 					startup.outbuf_drain_timeout = atoi(str);
 				break;
-			case 24:
+			case 25:
 				startup.options ^= BBS_OPT_NO_EVENTS;
 				break;
-			case 25:
+			case 26:
 				startup.options ^= BBS_OPT_NO_QWK_EVENTS;
 				break;
-			case 26:
+			case 27:
 				startup.options ^= BBS_OPT_NO_HOST_LOOKUP;
 				break;
 			default:
diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h
index e4ac56eae371209507a3ba0484a0a23d5c1dce04..3960c081c78492373c066719c3d36d7856f78eac 100644
--- a/src/sbbs3/startup.h
+++ b/src/sbbs3/startup.h
@@ -127,6 +127,7 @@ typedef struct {
 	uint16_t	pet80_port;			// 80-column PETSCII terminal server
 	uint16_t	ssh_port;
 	uint16_t	ssh_connect_timeout;
+	int			ssh_error_level;
 	uint16_t	outbuf_highwater_mark;	/* output block size control */
 	uint16_t	outbuf_drain_timeout;
 	struct in_addr outgoing4;