Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
b298b58
Initial plan
Copilot Nov 6, 2025
9b74b83
Add fundamentals documentation: getting-started, gpio-basics, protoco…
Copilot Nov 6, 2025
85be084
Add reading-datasheets guide and protocol documentation including UART
Copilot Nov 6, 2025
833984e
Add platform guides, glossary, troubleshooting, project setup, and de…
Copilot Nov 6, 2025
24108f0
Update main Documentation README with new structure and navigation
Copilot Nov 6, 2025
9668133
Fix variable name inconsistency in gpio.md code example
Copilot Nov 6, 2025
b6fbe45
Remove unicode emojis from section titles and reorganize structure
Copilot Nov 13, 2025
e571139
Remove unicode emojis from all documentation files
Copilot Nov 13, 2025
1a5e30c
Restructure protocol documentation with consistent format: what it is…
Copilot Dec 18, 2025
5e2bb42
Remove backup file accidentally committed
Copilot Dec 18, 2025
5edae09
Fix critical API issues, broken links, stale content, and address all…
Copilot Apr 2, 2026
4fda4a7
Fix markdownlint errors in protocol documentation
Copilot Apr 2, 2026
faca762
Fix markdownlint errors in Documentation/fundamentals/ files
Copilot Apr 2, 2026
40385c1
Fix markdownlint errors in documentation files
Copilot Apr 2, 2026
c830b31
Fix markdownlint errors in documentation files
Copilot Apr 2, 2026
0f7ff03
Fix markdownlint errors in troubleshooting.md
Copilot Apr 2, 2026
369d73e
Fix MD060/table-column-style markdownlint errors in documentation
Copilot Apr 2, 2026
83ba5b0
Fix driver auto-detection docs, systemctl command, I2C leak, markdown…
Copilot Apr 2, 2026
2559a0f
Fix broken link to non-existent Visual Studio IoT page
joperezr Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 110 additions & 95 deletions Documentation/README.md

Large diffs are not rendered by default.

583 changes: 583 additions & 0 deletions Documentation/deployment/containers.md

Large diffs are not rendered by default.

124 changes: 124 additions & 0 deletions Documentation/deployment/cross-compilation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# How to Deploy an IoT App
Comment thread
joperezr marked this conversation as resolved.

This provides information on how to publish and deploy a .NET IoT application to a development board like a Raspberry Pi.

## Using .NET CLI (Recommended)

### Publish for Raspberry Pi

```bash
# Framework-dependent (requires .NET runtime on target)
dotnet publish -c Release -r linux-arm64 --self-contained false

# Self-contained (includes .NET runtime - larger but no runtime needed)
dotnet publish -c Release -r linux-arm64 --self-contained true
```

**Common Runtime Identifiers (RIDs):**

| Target | RID |
| ------------------------------- | ------------- |
| Raspberry Pi 3/4/5 (64-bit OS) | `linux-arm64` |
| Raspberry Pi 3/Zero (32-bit OS) | `linux-arm` |

### Deploy to Raspberry Pi

**Using SCP (Secure Copy):**

```bash
# Copy published files to Raspberry Pi
scp -r bin/Release/net8.0/linux-arm64/publish/* pi@raspberrypi.local:~/myiotapp/

# SSH into Pi and run
ssh pi@raspberrypi.local
cd ~/myiotapp
chmod +x MyIotApp
./MyIotApp
```

**Using rsync (faster for updates):**

```bash
rsync -avz bin/Release/net8.0/linux-arm64/publish/ pi@raspberrypi.local:~/myiotapp/
```

## Using Visual Studio

### Publish Profile

1. Right-click the project in Solution Explorer → **Publish...**
2. Select **Folder** as the target
3. Click **Configure...**
4. Set the following:
- **Target Framework:** net8.0
- **Deployment Mode:** Framework-dependent or Self-contained
- **Target Runtime:** linux-arm64 (for 64-bit Pi) or linux-arm (for 32-bit Pi)
5. Click **Publish**

### Example Publish Profile (.pubxml)

```xml
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<TargetFramework>net8.0</TargetFramework>
<PublishDir>bin\publish</PublishDir>
<RuntimeIdentifier>linux-arm64</RuntimeIdentifier>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
```

## Deployment Options

### Framework-Dependent Deployment

- **Smaller package size** - only your app, not the runtime
- **Requires .NET runtime on target** - install with: `curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin`
- **Recommended** for development boards with internet access

### Self-Contained Deployment

- **Larger package** - includes .NET runtime (~50-80 MB)
- **No runtime installation needed** on target
- **Recommended** for embedded or offline deployments

### Single-File Publishing

Create a single executable:

```bash
dotnet publish -c Release -r linux-arm64 --self-contained true /p:PublishSingleFile=true
```

### Trimming (Reduce Size)

Trim unused code for smaller deployments:

```bash
dotnet publish -c Release -r linux-arm64 --self-contained true /p:PublishTrimmed=true
```

**Note:** Trimming may remove code accessed via reflection. Test thoroughly.

## File Transfer Tools

- **SCP/SFTP** - Built into most terminals (`scp`, `sftp`)
- **rsync** - Efficient incremental file sync
- **FileZilla** - GUI-based SFTP client
- **Visual Studio Code Remote SSH** - Edit and deploy directly

## References

- [.NET Application Deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/)
- [dotnet publish command](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish)
- [.NET RID Catalog](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog)
- [Visual Studio Publish Profiles](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/visual-studio-publish-profiles)

## See Also

- [Running in Docker Containers](containers.md) - Containerize your IoT apps
- [Auto-start on Boot](systemd-services.md) - Run apps automatically with systemd
152 changes: 152 additions & 0 deletions Documentation/deployment/systemd-services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# How to start app automatically on boot using systemd

## Create your app

For the purpose of this document let's assume you have deployed your app under:

`
/home/pi/myiotappfolder/myiotapp
`

The app name is `<myiotapp>` in this documentation you would replace the entire string including the carrots in your files.

To run this you will need to make your app run as root please read the section on [Security Considerations](#security-considerations)

Make sure to make your app ```<myiotapp>``` is executable by using the command:

```shell
# Requires root permissions
chmod +x <myiotapp>
```

## Create systemd.service unit

For this example a script titled `<myiotapp>.service` will be used. The folder that this application is ran from is `/home/pi/myiotappfolder` Please replace accordingly with your app name or the location you decide to save your script. Remember to add the `.service` as the file extension

Here is an example systemd.service file that you can use as a template. Make sure to use a Unix end of line when creating the systemmd.service file.

```shell
[Unit]
#The # is a comment line
#Documentation https://www.freedesktop.org/software/systemd/man/systemd.service.html

#Place short description here
Description=My IOT Device Service

#This will not start execution of this file until the network connection is made
#It can be replaced with other parameters of your choosing
After=network.target

[Service]
#Default: Startup type
Type=Simple

#Edit this with your file name. In this example the app executable is in the /home/pi/myiotappfolder
#The file we are running and made executable is <myiotapp>
#ExecStart runs this executable script
ExecStart=/home/pi/myiotappfolder/myiotapp

#Optional: Saves the output and error log of the terminal to a .log file in a directory of your choosing.
StandardOutput=file:/home/pi/myiotapp.log
StandardError=file:/home/pi/myiotapp-error.log

#Optional: To cleanly end the file on stop use this command. This sends a terminal interrupt command on the executable script
KillSignal=SIGINT

#Automatically restart on kill
Restart=always

[Install]
WantedBy=multi-user.target

```

The systemmd service file which we will call `<myiotapp>.service` must be saved to `/etc/systemd/system` to be ran on boot.

Note that you must have admin priviliges to save a file to the system etc folder. You can use the following to copy the service in a terminal to this folder:

```shell
# Requires root permissions
cp <myiotapp>.service /etc/systemd/system
```

Once in the folder make the file executable by going to the directory and then use the chmod command:

```shell
# Requires root permissions
chmod +x <myiotapp>.service
```

### Notes

Please use care and refer to the manual when using this code
You may also look at the other scripts under /etc/systemd/system for reference.

## Test your service

This will start the service but will not run it on boot.

```shell
# Requires root permissions
systemctl start <myiotapp>.service
```

Now you can look at the log file you created to see the output of the terminal. `/home/pi/myiotapp.log`

Or you can check the status of the service by using in a terminal:

```shell
# Requires root permissions
systemctl status <myiotapp>.service
```

To stop the service run:

```shell
# Requires root permissions
systemctl stop <myiotapp>.service
```

## To make your service automatically run on boot

```shell
# Requires root permissions
systemctl daemon-reload
systemctl enable <myiotapp>.service
```

## To disable your service

Run this in terminal to disable the program on boot:

```shell
# Requires root permissions
systemctl daemon-reload
systemctl disable <myiotapp>.service
```

## Security considerations

Your app will be running with root permissions.

Please ensure only root can write to the files related with your app.
That includes any binary dependencies or any other scripts which you app may run.

Not doing so may add a risk of elevation of privileges to your device.

```shell
# The commands below should be run as root (i.e. sudo)

# Owner of every dependency and app should be root
chown -R root:root /your/app/directory/

# permissions for dependencies (files) should be rw for owner, read or none for anyone else
chmod -R 644 /your/app/directory/*

# your app additionally will need executable permissions which you may have accidentally removed with previous command
chmod 755 /your/app/directory/yourapp

# permissions for directories/subdirectories
chmod 755 /your/app/directory
chmod 755 /your/app/directory/subdirectory
```
Loading
Loading