A collection of practical notes, commands, configuration examples, and troubleshooting solutions for Windows, Linux, MikroTik RouterOS, office hardware, Raspberry Pi, Python, Django, and web development.
These notes are based on real-world system administration and software development experience.
Warning: Some operations described below modify the Windows Registry, boot configuration, firewall state, or router configuration. Always create a backup before making changes on production systems.
Useful Windows commands, PowerShell examples, registry fixes, and troubleshooting techniques.
Windows includes the tzutil utility for viewing and changing the system time zone.
tzutil /g
tzutil /l
For example:
tzutil /s "FLE Standard Time"
The FLE Standard Time zone is commonly used for Eastern European locations.
The command is available in desktop and server editions of Windows.
Windows can display passwords for wireless networks previously saved on the computer.
Open Command Prompt and run:
netsh wlan show profiles
Replace Wi-Fi-Profile with the actual profile name:
netsh wlan show profile name="Wi-Fi-Profile" key=clear
Look for the following field in the output:
Key Content
The command must be run by a user who has permission to access the saved wireless configuration.
A Security Identifier, or SID, is often required when working with permissions or registry keys under HKEY_USERS.
Run:
whoami /user
Example output:
USER INFORMATION
----------------
User Name SID
=============== =============================================
DOMAIN\User S-1-5-21-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXX-1001
Windows classifies network connections as:
Changing the profile may be necessary for Remote Desktop, file sharing, network discovery, or firewall configuration.
Open PowerShell as Administrator.
Display all current profiles:
Get-NetConnectionProfile
Example output:
Name : Unidentified network
InterfaceAlias : Ethernet 3
InterfaceIndex : 19
NetworkCategory : Public
IPv4Connectivity : NoTraffic
IPv6Connectivity : NoTraffic
Change a specific interface to Private:
Set-NetConnectionProfile -InterfaceIndex 19 -NetworkCategory Private
Verify the result:
Get-NetConnectionProfile -InterfaceIndex 19
Change all detected profiles to Private:
Get-NetConnectionProfile |
Set-NetConnectionProfile -NetworkCategory Private
Warning: Do not set untrusted public networks to
Private. A private profile normally enables less restrictive firewall rules.
Open Registry Editor:
regedit.exe
Navigate to:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles
Locate the required profile using its ProfileName value.
Edit the Category DWORD value:
| Value | Network category |
|---|---|
0 |
Public |
1 |
Private |
2 |
Domain |
A domain-authenticated profile is normally assigned automatically by Windows. Manually setting the registry value does not guarantee successful domain authentication.
Run:
secpol.msc
Open:
Network List Manager Policies
Here you can define network location behavior and restrict users from changing network profiles.
When troubleshooting outdated or incorrect DNS responses, check both the DNS server and the client computer.
Run this command on a Windows Server with the DNS Server role:
dnscmd /clearcache
An alternative PowerShell command is:
Clear-DnsServerCache -Force
Run on the affected workstation or server:
ipconfig /flushdns
When necessary:
ipconfig /registerdns
The local Hosts file overrides normal DNS resolution:
C:\Windows\System32\drivers\etc\hosts
Old entries in this file can make a valid DNS configuration appear broken.
Windows can automatically log in with a local or domain account.
Security warning: This method stores the account password in the registry. Do not use it on an untrusted or shared computer.
Open Registry Editor and navigate to:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
Create or modify the following string values:
| Registry value | Example |
|---|---|
DefaultUserName |
username |
DefaultPassword |
password |
DefaultDomainName |
DOMAIN or computer name |
AutoAdminLogon |
1 |
If DefaultPassword does not exist:
DefaultPassword.Restart Windows to test the configuration.
To disable automatic logon, change:
AutoAdminLogon=0
Windows may display a recovery or boot options screen after a power failure, failed boot, or BSOD.
To ignore all recorded boot failures:
bcdedit /set {current} bootstatuspolicy IgnoreAllFailures
To ignore failures caused by an unexpected shutdown:
bcdedit /set {current} bootstatuspolicy IgnoreShutdownFailures
These options may be useful for:
Warning: Disabling recovery screens can hide a genuine boot problem. Use this configuration only when automatic startup is more important than interactive recovery.
To restore the standard policy:
bcdedit /deletevalue {current} bootstatuspolicy
A legacy Outlook installation may repeatedly start in Safe Mode because of an incorrect calendar-related registry value.
First, find the user's SID:
whoami /user
Then open Registry Editor and navigate to:
HKEY_USERS\<USER-SID>\Software\Microsoft\Office\15.0\Outlook\Options\Calendar
Locate the following DWORD value:
Calendar Type
Change its value from:
1
to:
0
Restart Outlook.
Office\15.0corresponds to Office 2013. Other Office releases use different version numbers, so this fix should not be applied blindly to every Outlook installation.
termsrv.dllSystem File Checker may report that it cannot repair termsrv.dll or a related Terminal Services component.
Start by running:
sfc /scannow
Review the component servicing log:
C:\Windows\Logs\CBS\CBS.log
To extract SFC-related entries:
findstr /c:"[SR]" C:\Windows\Logs\CBS\CBS.log > "%USERPROFILE%\Desktop\sfc-details.txt"
Before editing the registry, repair the Windows component store:
DISM /Online /Cleanup-Image /ScanHealth
Then run:
DISM /Online /Cleanup-Image /RestoreHealth
Restart Windows and run SFC again:
sfc /scannow
On older Windows versions, the error may reference a component name similar to:
x86_microsoft-windows-t..teconnectionmanager_31bf3856ad364e35_6.0.6001.18000_none_8e9f41c854441762
A historical workaround involved searching for the exact component identifier in Registry Editor, exporting the matching key, and deleting the invalid entry.
High-risk operation: Do not delete Component Based Servicing or
WinSxSregistry entries unless you have a complete backup and understand the consequences. Incorrect changes can make Windows servicing and updates unusable.
The preferred procedure on supported Windows versions is to use DISM, SFC, Windows Update, or an in-place repair installation.
Practical MikroTik commands for configuration exports, interface management, bridge MAC addresses, and connection tracking.
A RouterOS text export creates a readable .rsc file.
Create an export:
/export file=config-backup
RouterOS creates:
config-backup.rsc
A text export is useful for:
To include passwords and other sensitive values:
/export show-sensitive file=config-backup-sensitive
Security warning: A sensitive export may contain Wi-Fi passwords, VPN secrets, user credentials, and other private information. Store it securely and never publish it in a public repository.
Import a previously created .rsc script:
/import file-name=config-backup.rsc
Depending on the RouterOS version, the shorter syntax may also work:
/import file=config-backup.rsc
A text export is not identical to a binary system backup. Importing a full configuration into a different router model may require manual editing of interface names and hardware-specific settings.
Create a complete binary backup:
/system backup save name=router-backup
Create an encrypted backup:
/system backup save name=router-backup password="StrongBackupPassword"
Restore it with:
/system backup load name=router-backup.backup
Binary backups are best restored to the same router model and a compatible RouterOS version.
For devices using the legacy Wireless package:
/interface wireless export show-sensitive
For devices using the newer WiFi menu:
/interface wifi export show-sensitive
Without show-sensitive, RouterOS hides passwords and other secrets.
Only administrators with sufficient permissions should be able to display sensitive configuration.
/interface ethernet set [find name="ether1"] mac-address=02:23:45:67:89:00
/interface bridge set [find name="bridge1"] \
admin-mac=02:23:45:67:89:00 \
auto-mac=no
/interface wireless set [find name="wlan1"] \
mac-address=02:23:45:67:89:00
Use a locally administered unicast MAC address. Addresses beginning with
02are commonly used for manually assigned local MAC addresses.
Not every interface type or hardware model allows its physical MAC address to be changed.
By default, RouterOS can automatically select the bridge MAC address from one of its member interfaces.
Display bridge information:
/interface bridge print detail
Example:
name="bridge1"
mac-address=4E:A4:50:F4:E7:1C
auto-mac=yes
To keep the current MAC address permanently, configure it as the administrative MAC:
/interface bridge set [find name="bridge1"] \
admin-mac=4E:A4:50:F4:E7:1C \
auto-mac=no
Verify the result:
/interface bridge print detail
The bridge should now show:
auto-mac=no
admin-mac=4E:A4:50:F4:E7:1C
A static bridge MAC can help prevent unexpected MAC changes after:
RouterOS connection tracking keeps active TCP, UDP, and other tracked connections.
Sometimes an existing session must be terminated immediately after changing NAT, routing, firewall, or policy-routing rules.
/ip firewall connection remove [
find where dst-address~"8.8.8.8" protocol=tcp
]
One-line version:
/ip firewall connection remove [find where dst-address~"8.8.8.8" protocol=tcp]
/ip firewall connection print where dst-address~"8.8.8.8" protocol=tcp
Always preview the result before using remove on a production router.
RouterOS does not provide a normal Linux shell with apt, pip, Python virtual environments, or standard Python package management.
There are three practical ways to use Python with MikroTik.
Create a virtual environment on Linux, macOS, Windows, or a VPS:
python3 -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
Install a RouterOS API library:
pip install librouteros
Python can then connect to the router through:
This is generally the simplest and safest approach.
Some ARM64 and x86 MikroTik devices can run Linux containers.
A compatible Linux container image can include:
pip;Container support must be explicitly installed and enabled. It also requires enough storage and memory.
Do not run large application workloads on a router unless the device has sufficient resources and the network impact is understood.
For simple automation, use the built-in RouterOS scripting language:
/system script add name=test-script source={
:log info "RouterOS script started"
}
Run the script:
/system script run test-script
Native scripts are suitable for:
Practical Linux administration examples for Python applications and systemd services.
Running a Python bot through systemd provides:
The following example assumes the application is located in:
/home/Bot
Open the application directory:
cd /home/Bot
Create the virtual environment:
python3 -m venv venv
Activate it:
source venv/bin/activate
Upgrade pip:
python -m pip install --upgrade pip
Install the required packages:
pip install -r requirements.txt
If the project does not yet have a requirements file:
pip freeze > requirements.txt
For example:
nano /home/Bot/bot.py
Minimal test application:
import logging
import time
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
logging.info("Bot started")
while True:
time.sleep(60)
Create the service file:
sudo nano /etc/systemd/system/bot.service
Add:
[Unit]
Description=Python Bot
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=bot
Group=bot
WorkingDirectory=/home/Bot
ExecStart=/home/Bot/venv/bin/python /home/Bot/bot.py
Restart=on-failure
RestartSec=5
Environment=PYTHONUNBUFFERED=1
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
This method starts the Python interpreter from the virtual environment directly. A separate start.sh script is normally unnecessary.
Replace
User=botandGroup=botwith the actual unprivileged Linux account that owns and runs the application.
sudo systemctl daemon-reload
sudo systemctl enable --now bot.service
Check its status:
sudo systemctl status bot.service
Display recent logs:
sudo journalctl -u bot.service -n 100 --no-pager
Follow logs in real time:
sudo journalctl -u bot.service -f
Restart the bot:
sudo systemctl restart bot.service
Stop it:
sudo systemctl stop bot.service
Disable automatic startup:
sudo systemctl disable bot.service
A startup script can still be useful when several commands must run before the application.
Create:
nano /home/Bot/start.sh
Add:
#!/usr/bin/env bash
set -euo pipefail
cd /home/Bot
exec /home/Bot/venv/bin/python /home/Bot/bot.py
Make it executable:
chmod +x /home/Bot/start.sh
Use it in the service:
ExecStart=/home/Bot/start.sh
Using exec ensures that systemd tracks the Python process correctly.
The following script reads the Raspberry Pi CPU temperature and controls a fan through GPIO.
It uses two different thresholds:
45°C;35°C.This difference is called hysteresis. It prevents the fan from switching on and off repeatedly near one temperature.
The
gpiocommand shown below is associated with older WiringPi-based installations. Modern Raspberry Pi systems may useraspi-gpio,pinctrl,libgpiod, or a Python GPIO library instead.
Create the script:
nano /usr/local/bin/fan-control.sh
Add:
#!/usr/bin/env bash
set -u
TEMP_FILE="/sys/class/thermal/thermal_zone0/temp"
GPIO_PIN=7
TURN_ON_TEMP=45000
TURN_OFF_TEMP=35000
if [[ ! -r "$TEMP_FILE" ]]; then
echo "Temperature sensor file is unavailable: $TEMP_FILE" >&2
exit 1
fi
temp=$(<"$TEMP_FILE")
if ! [[ "$temp" =~ ^[0-9]+$ ]]; then
echo "Invalid temperature value: $temp" >&2
exit 1
fi
echo "Current temperature: $((temp / 1000))°C"
gpio mode "$GPIO_PIN" out
if (( temp > TURN_ON_TEMP )); then
gpio write "$GPIO_PIN" 1
echo "Temperature is above 45°C. Cooling fan enabled."
elif (( temp < TURN_OFF_TEMP )); then
gpio write "$GPIO_PIN" 0
echo "Temperature is below 35°C. Cooling fan disabled."
else
echo "Temperature is inside the hysteresis range. Fan state unchanged."
fi
Make it executable:
sudo chmod +x /usr/local/bin/fan-control.sh
Test it:
sudo /usr/local/bin/fan-control.sh
Open the root crontab:
sudo crontab -e
Run the script once per minute:
* * * * * /usr/local/bin/fan-control.sh >> /var/log/fan-control.log 2>&1
For faster and more reliable control, create a continuously running service instead of invoking the script through cron.
Verify whether the GPIO number refers to WiringPi numbering, BCM numbering, or the physical header pin. Connecting a fan directly to a GPIO pin can damage the Raspberry Pi. Use a transistor or MOSFET driver and a flyback diode when controlling an inductive load.
Many network-connected Samsung printers and multifunction devices provide a browser-based administration interface called SyncThru Web Service.
Find the printer's IP address and open it in a browser:
http://PRINTER-IP
Example:
http://192.168.1.50
Some devices may use HTTPS:
https://192.168.1.50
Some older Samsung devices used the following defaults:
Username: admin
Password: sec00000
Some older models used:
Password: 1111
These credentials will not work when:
Change all default credentials before placing a printer on a trusted business network. The web interface should not be exposed directly to the Internet.
If the password is unknown, consult the device manual or follow the model-specific reset procedure.
An HTML <datalist> provides autocomplete suggestions while still allowing the user to enter a custom value.
This is useful for fields such as:
A common mistake is to generate raw HTML inside the Django view or edit Django's files inside site-packages. Neither approach is necessary.
The cleaner solution is:
TextInput;list attribute pointing to a <datalist> element.from django.conf import settings
from django.db import models
class AddInfo(models.Model):
work_where = models.CharField(max_length=255)
work_who = models.CharField(max_length=255)
work_what = models.TextField(blank=True)
work_minutes = models.PositiveIntegerField(default=0)
work_user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
)
def __str__(self) -> str:
return f"{self.work_where}: {self.work_what[:50]}"
Use TextInput for fields connected to a datalist:
from django import forms
from .models import AddInfo
class AddInfoForm(forms.ModelForm):
class Meta:
model = AddInfo
fields = [
"work_where",
"work_who",
"work_what",
"work_minutes",
"work_user",
]
widgets = {
"work_where": forms.TextInput(
attrs={
"list": "work-where-options",
"autocomplete": "off",
}
),
"work_who": forms.TextInput(
attrs={
"list": "work-who-options",
"autocomplete": "off",
}
),
"work_what": forms.Textarea(
attrs={
"cols": 80,
"rows": 5,
}
),
}
labels = {
"work_where": "Place or office",
"work_who": "Employee",
"work_what": "Comment",
"work_minutes": "Working time",
}
The important part is:
attrs={"list": "work-where-options"}
Its value must match the id of the corresponding <datalist> element.
from django.shortcuts import render
from .forms import AddInfoForm
from .models import AddInfo
def add_info(request):
if request.method == "POST":
form = AddInfoForm(request.POST)
if form.is_valid():
form.save()
form = AddInfoForm()
else:
form = AddInfoForm()
work_where_options = (
AddInfo.objects
.exclude(work_where="")
.values_list("work_where", flat=True)
.distinct()
.order_by("work_where")
)
work_who_options = (
AddInfo.objects
.exclude(work_who="")
.values_list("work_who", flat=True)
.distinct()
.order_by("work_who")
)
context = {
"form": form,
"work_where_options": work_where_options,
"work_who_options": work_who_options,
}
return render(request, "reports/add_info.html", context)
Using distinct() allows the database to remove duplicate values.
There is no need to:
safe filter;<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
<datalist id="work-where-options">
{% for value in work_where_options %}
<option value="{{ value }}"></option>
{% endfor %}
</datalist>
<datalist id="work-who-options">
{% for value in work_who_options %}
<option value="{{ value }}"></option>
{% endfor %}
</datalist>
Django automatically escapes template values, which is safer than constructing raw HTML in the view.
When the project uses a Bootstrap form package, the datalists remain the same:
{% load bootstrap5 %}
<form method="post">
{% csrf_token %}
{% bootstrap_form form %}
<button type="submit" class="btn btn-primary">
Submit
</button>
</form>
<datalist id="work-where-options">
{% for value in work_where_options %}
<option value="{{ value }}"></option>
{% endfor %}
</datalist>
<datalist id="work-who-options">
{% for value in work_who_options %}
<option value="{{ value }}"></option>
{% endfor %}
</datalist>
A datalist works with:
<input type="text">
It does not provide the same behavior for a <textarea>.
Therefore, the Django widget must be:
forms.TextInput
and not:
forms.Textarea
site-packagesAvoid modifying:
venv/lib/pythonX.X/site-packages/django/forms/templates/
Such changes:
Configure the list attribute through the form widget instead.
Unlike a <select> element, a datalist only provides suggestions. The user can still type a value that is not in the list.
Use a model relation or custom validation when only predefined values should be allowed.
The examples on this page cover several generations of operating systems and software.
Before applying a command:
Last updated: August 2026